Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Vấn đề trừu tượng

Làm thế nào để nhập tốt nhất một gói có thể hoặc không thể nhập thành công trong quá trình chạy chương trình Tkinter, giả sử trên một nút nhấn.

Hiện tại tôi đang sử dụng:

def ButtonFunction(self):

    try:
         import package
    except Exception as e: 
         print(e)  # I don't want the execution to stop if this cannot be imported. 

Đây có phải là cách tốt nhất để đi về nó? Có vấn đề gì với việc nhập các gói trong một cuộc gọi chức năng không?

Vấn đề cụ thể

Tôi đang sử dụng CiruitPython để liên lạc với bảng MCP2221 nhưng nhập chỉ hoạt động nếu bảng được kết nối. Tôi muốn chương trình vẫn hoạt động nếu bảng không được kết nối và một cách để người dùng kết nối bảng sau khi chương trình bắt đầu.

Mã cụ thể:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')

Cụ thể

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
0 và
(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
1 sẽ không nhập nếu không có bảng được phát hiện nên tôi đã chuyển mã này từ nơi tất cả các nhập khẩu khác vào chức năng sẽ khởi tạo tất cả các phần cứng.

Giới thiệu Django - Khởi tạo project

Sơ qua về Django

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Django là một Framework lập trình web bậc cao được viết bằng ngôn ngữ lập trình Python.

Django nhanh và đơn giản giúp chúng ta có thể lập trình web trong thời gian ngắn. Ngoài ra, Django còn có tài liệu rất tốt, cộng đồng Django đông và lớn mạnh.

Nó tuân theo nguyên tắc DRY (Don't repeat yourself - Đừng lặp lại chính mình), trong khi những Framework khác lại không coi trọng điều này. Django cũng hỗ trợ ORM (Object Relistic Mapping)

Mô hình MTV pattern:

  • Django tuân theo mô hình MTV (Model-Template-View) thay vì mô hình MVC (Model-View-Controller)
  • Mô hình được dùng khi tạo ứng dụng tương tác với người dùng.
  • Mô hình này bao gồm code HTML với DJango Template Language (DTL)
  • View (tương ứng với Controller của MVC) là mã được viết để kiểm soát sự tương tác giữa Model và Template, nói cách khác là điều ướng các Request từ Client gửi lên Server và trả về kết quả từ Server xuống Client.

Để code Django, chúng ta phải cài đặt được Python. Bạn có thể cài đặt Python và Pip ở hướng dẫn này, đây là hướng dẫn cài đặt với Ubuntu và mình cũng sẽ code trên hệ điều hành Ubuntu.

Phiên bản Python mình sử dụng là Python 3.7, các bạn cũng có thể cài đặt Python với các phiên bản

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
2 khác.

Khởi tạo project

Việc đầu tiên là cài đặt môi trường ảo để phát triển dự án, có rất nhiều thư viện python có thể làm được điều này từ virtualenv đến pipenv. Để thuận tiện, mình sử dụng luôn pipenv để triển khai cài đặt. Ta chạy lệnh

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
3

Tiếp theo là tạo folder chứa project và chạy môi trường ảo:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell

Lúc này, command line có dạng

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
4 tức là chúng ta đang trong môi trường ảo là
(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
5.

Tạo code project với lệnh

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
6. Lệnh này sẽ tạo tất cả code cần có cho 1 project Django ban đầu, mình thêm dấu
(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
7 vào cuối, sẽ hơi khác so với thông thường khi không có dấu
(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
7

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver

Lúc này, command line sẽ xuất hiện 1 đường dẫn http://127.0.0.1:8000/ và chúng ta truy cập vào đường dẫn này sẽ có dạng:

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Cấu trúc thư mục của project:

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)

Kết nối với MySQL

Mỗi Framework lập trình web nào cũng cần phải có cơ sở dữ liệu để quản lý dữ liệu người dùng. Nhìn thoáng qua file

(GreatKart)...$ python3 manage.py migrate
(GreatKart)...$ python3 manage.py runserver
9 và kéo xuống phần
---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
0:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

Ở đây, mặc định thì Django đang sử dụng hệ quản trị CSDL là sqlite3 cũng chính vì thế khi bạn chạy lệnh migrate bên trên, folder code sẽ tự tạo file

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
1. Django hỗ trợ rất nhiều hệ quản trị CSDL phổ biến cả sql lẫn nosql, chính vì thế mình sẽ sử dụng luôn MySQL làm hệ quản trị CSDL thay cho sqlite3.

Để sử dụng được MySQL, chúng ta có thể cài đặt MySQL ở đây, bạn chỉ cần làm đến bước

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
2 là đủ rồi. Ngoài ra, để thuận tiên cho quản lý MySQL bằng giao diện, bạn có thể cài luôn MySQL Workbench ở đây. Còn nữa, chúng ta cũng cần phải cài đặt thư viện
---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
3 để Python kết nối đến MySQl bằng lệnh
---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
4

Mình chỉnh sửa lại code

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
0 trong file
---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
6 1 chút:

DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}

Thế là xong, bạn chạy lại lệnh

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
7, nếu command line không báo lỗi thì chúng ta đã kết nối thành công, lúc này bạn có thể xóa file
---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
8 rồi.

Để tên database và pasword thế này thì hớ hênh quá, chúng ta phải tạo thêm biến

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
9 để không bị lộ những thứ cá nhân thế này và những thứ khác sau này cũng thế. Thư viện Python cần cài đặt tiếp đó là
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
0, sau đó bạn tạo luôn file
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
1 cùng cấp với
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
2 với nội dung:

SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi

Trong file

---GreatKart
      |---greatkart (folder)
      |---manage.py
      |---db.sqlite3
      |---Pipfile
      |---Pipfile.lock (Nếu chưa có, mình tạo bằng cách chạy `pipenv lock`)
      |---requirements.txt (mình tạo bằng lệnh)
      |---.gitignore (mình tự tạo thêm)
6 bạn phải có thêm:

# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()

và bạn chỉ cần thay những thứ tương ứng từ file

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
1 vào:

SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")

Chúng ta lại chạy lại câu lênh

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
5 và
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
6 như bên trên, nếu không có lỗi gì thì ổn rồi.

Docker cho project

Ta thoát khỏi môi trường ảo trong phần 1 bằng lệnh

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
7, tạo 2 file Dockerfile và docker-compose.yml:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
0

Nội dung file Dockerfile như sau:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
1

Các nội dung này khá quen thuộc với người dùng Docker thường xuyên nên mình cũng không giải thích code nữa.

Nội dung file docker-compose.yml như sau:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
2

Ở file

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
8 này, chúng ta tạo 2 container là web (để chạy ứng dụng web của chúng ta) và db (để chạy phần cơ sở dữ liệu MySQL)

Bạn cần chú ý, giá trị của

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
9 phải là tên container cơ sở dữ liệu (db). Trong container db chứa image có tên
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
0 tức là phải là phiên bản MySQl trong máy chúng ta, giá trị volumes bắt đầu với
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
1 cũng phải tương ứng với tên container, giá trị ports bạn phải đặt thành
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
2 (
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
3 không phải là 3306 để không bị trùng port). Cả 2 container phải có giá trị
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
4 do chúng ta đang dùng biến môi trường

Ngoài ra, file

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
1 bạn cũng cần đổi lại giá trị của
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
6 thành
DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
7 (tên container db)

Chúng ta chạy các lệnh sau đển run docker:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
3

Bạn mở thêm 1 tab command line nữa và chạy

DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
8 để kết nối CSDL với container db của Docker

Nếu cả các lệnh trên không báo lỗi và chúng ta truy cập lại trang http://127.0.0.1:8000/ vẫn như cũ thì ổn rồi. Lúc này, chúng ta đang chạy web với docker mà không cần phải vào môi trường ảo (

DATABASES = {
    'default': {
        'ENGINE': "django.db.backends.mysql",
        'HOST': "localhost",
        'NAME': "GreatKart", # Đừng quên phải tạo trước Schema có tên 'GreatKart' trong MySQL
        'USER': "root",
        'PASSWORD': "12345678",
    }
}
9) mới có thể chạy được như phần 1 nữa.

Nếu xảy ra một số lỗi khi chạy thì các bạn có thể search Google để fix lỗi

Cài đặt Static và Media

Thư mục static trong Django là nơi chứa các folder, file tĩnh. Bao gồm: folder css, javascipt, font và các file ảnh cố định cho trang web.

Ngoài ra, mình cũng dowload các file cần thiết trong bootstrap 4 về để dùng, các bạn có thể sử dụng thư viện django-bootstrap4 nếu không muốn dùng nó trong static. Code cần thiết cho thư mục static mình để ở đây, các bạn có thể download về để sử dụng ngay.

Tiếp theo, đi đến file settings.py chúng ta thêm đoạn code sau để Django nhận biết thư mục static:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
4

Ở đây,

SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
0 và
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
1 là nơi Django lưu trữ các file static thông qua lệnh quản lý collectstatic khi deploy.
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
2 để Django thông qua đó tìm kiếm tất cả các file static rồi nạp vào nơi lưu trữ

Thư mục static vừa tải xuống bên trên mình để ở trong thư mục con

SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
3, cùng cấp với file settings.py. Tiếp theo ta chạy lệnh
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
4, thì Django sẽ tạo thư mục có đường dẫn như trong biến
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
0, cùng cấp với thư mục
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
3.

Nếu sau này chúng ta muốn thay đổi thư mục static, ta chỉ cần sửa thư mục static cùng cấp với settings.py, rồi chạy lại lệnh collectstatic để khởi tạo lại thư mục static mới.

Media là thư mục lưu trữ các file có kiểu media như các ảnh, video. Từ đó, server có thể truy cập để thêm, sửa, xóa trong đó. Cấu hình cho media như sau:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
5

Lần này chúng ta không cần làm gì thêm nữa. Nếu có lệnh truy cập thì Django sẽ tìm thư mục Media hoặc sẽ tạo nó nếu chưa có.

Tùy chỉnh user model, category, product model

Trong Django, framework này đã tạo 1 mô hình mặc định cho người dùng có tên là user. Chúng ta nên tùy chỉnh và kế thừa các hàm từ đó vì việc mặc định này thường hạn chế yêu cầu của nhà phát triển.

Tạo app mới có tên

SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
7 với lệnh
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
8, thêm
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
9 vào biến mảng
# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
0 trong file settings.py, cũng như thêm 1 biến mới
# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
1, biến này thông báo cho Django biết ta không còn dùng mô hình user mặc định nữa mà thay vào đó là
SECRET_KEY= ... # SECRET_KEY trong file settings.py 
DATABASE_ENGINE=django.db.backends.mysql
DATABASE_NAME=GreatKart
DATABASE_USER=root
DATABASE_PASSWORD=12345678
DATABASE_HOST=localhost
DATABASE_PORT=3306
TIME_ZONE=Asia/Ho_Chi_Minh
LANGUAGE_CODE=vi
7

Ta thêm class như sau vào file

# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
3:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
6

Thông tin các trường cần thiết cho bảng mới

# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
4 mình đã comment bên cạnh để mọi người hiểu chức năng.

Mình có tạo thêm class MyAccountManager để quản lý các thao tác người dùng:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
7

Chạy lệnh

# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
5 sau đó là
# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
6 để tạo bảng Account trong mysql. Và chạy lệnh
# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
7 để tạo 1 superadmin cho hệ thống. Lúc này các trường bạn phải điền đã giống với hàm create_superuser mà chúng ta đã tùy chỉnh.

Trong file

# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
8 ta tạo thêm class để superadmin có thể quản lý bảng này:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
8

Chúng ta truy cập đường dẫn

# Để lên trên
import environ
env = environ.Env(
    DEBUG=(bool, False)
)
environ.Env.read_env()
9 để đăng nhập và được các màn hình như sau:
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Tiếp theo, ta tạo app category với lệnh

SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
0 như trên, ta thêm class Category vào file
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
1 như sau:

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
9

Trường

SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
2 là để định danh cho 1 category, trường
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
3 sẽ cho phép truy cập thư mục
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
4, đừng lo nếu ta chưa có thư mục này, Django sẽ tự tạo nó. Trong class con Meta, ta khai báo biến
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
5 và
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
6 vì nếu không có thì trong trang superadmin sẽ hiển thị
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
7, điều này thì không đúng chỉnh tả. Chạy lệnh
SECRET_KEY = env("SECRET_KEY")
DATABASES = {
    "default": {
        "ENGINE": env("DATABASE_ENGINE"),
        "NAME": env("DATABASE_NAME"),
        "USER": env("DATABASE_USER"),
        "PASSWORD": env("DATABASE_PASSWORD"),
        "HOST": env("DATABASE_HOST"),
        "PORT": env("DATABASE_PORT"),
    }
}
LANGUAGE_CODE = env("LANGUAGE_CODE")
TIME_ZONE = env("TIME_ZONE")
8 và
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
5 để tạo bảng.

Thêm code cho file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
00 để superuser có thể quản lý bảng category:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
0

Chúng ta có giao diện cho phần quản lý category của superuser như sau:

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Tiếp theo, chúng ta tạo app store để quản lý bảng product với lệnh

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
01. Trong file
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
02 ta tạo class Product như sau:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
1

Trong file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
03 ta cũng thực hiện thêm app store để superuser quản lý:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
2

Ta có giao diện quản lý app product trong superuser như sau:

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Trong file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
04 ta tùy chỉnh biến urlpattern như sau:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
3

Ngoài ra, ở app store ta cũng tạo 1 file urls.py với biến

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
05:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
4

Trên đây, ta thực hiện khai báo các url trong file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
04, biến
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
05 khai báo các cụm đường dẫn đến các app khác. Django sẽ tự động tìm các đường dẫn từ file này. Biến
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
05 trong file
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
09 sẽ khai báo cụ thể các đường dẫn như thế nào. Nó có tiền tố kế thừa từ file url cha

Thiết kế Cart, CartItem model

Ta sẽ tạo 2 bảng cart và cart_item trong cùng 1 app là carts với lệnh

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
10. Ta tùy chỉnh file
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
11 với các class mới như sau:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
5

Và thêm đoạn code để superuser quản lý, ở file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
12:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
6

Bảng Cart có các bản ghi mô tả các giỏ hàng của người dùng, bao gồm cả người dùng đã đăng nhập và người dùng vãng lai (bản ghi được tạo dựa trên cookie của máy local).

Bảng CartItem với bản ghi tương ứng là các mục hàng trong giỏ hàng. Với 2 khóa ngoại là product và cart

Tùy chỉnh biến

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
13 trong file
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
14 như sau:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
7

Template cho trang home, store, product_detail

Đi đến trang settings.py, ta tùy chỉnh biến

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
15 ở cặp key-value như sau:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
8

Chúng ta tạo 1 folder đồng cấp với manager.py là

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
16 để Django tự động tìm folder này để load các file template.

Từ file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
17 ta thêm hàm
def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
18 để làm chức năng điều hướng request:

$ mkdir GreatKart && cd GreatKart # folder chứa code project
$ pipenv install Django # Django==3.2
$ pipenv shell
9

Từ folder template, ta tạo 1 file base.html làm file template cơ sở cho hầu hết các trang trong hệ thống. Và 1 file home.html làm trang chủ.

Tất cả các file template, các bạn có thể tham khảo ở đây

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Tiếp theo, ta tùy chỉnh file

def _init_hardware(self):
        try:    
            # Set an Environment Variable so Adafruit Blinka knows we're using the MCP2221
            os.environ["BLINKA_MCP2221"] = "1"
            import board
            import busio
        except:
            raise RuntimeError('Could not initialise Circuit Python. Check hardware is plugged in.')
19 để hiển thị trang store. Ngoài ra, ta cũng thêm các file template cho app store. Tất cả mình để ở link github bên trên. Ta sẽ hiển thị các trang như sau:
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu
Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Chúng ta thêm file template cho trang product-detail để được trang product-detail như sau:

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Kết thúc

Đến đây mình xin được dừng phần 1, phần 2 mình sẽ sớm tiếp tục việc hoàn thiện các chức năng:

  • Thêm, xóa sản phẩm vào giỏ hàng
  • Hoàn thiện các chức năng liên quan đến xác thực người dùng
  • Thực hiện thanh toán bằng paypal cho người dùng

Tạm biệt mọi người và hẹn gặp lại

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu

Update: Phần 2 và phần 3 mình đã hoàn thiện và đó cũng là tất cả các phần cho ứng dụng của mình rồi. Đừng quên cho mình 1 upvote và 1 bookmark ạ

Hướng dẫn python import on demand - python nhập khẩu theo yêu cầu