Remote Procedure Calls in Odoo

Máy chủ Odoo hỗ trợ các cuộc gọi thủ tục từ xa (RPC), bạn có thể kết nối tới instance Odoo từ các ứng dụng bên ngoài. Ví dụ: thông qua RPC bạn có thể lấy trạng thái của đơn đặt hàng, sau đó hiển thị trạng thái của đơn đặt hàng trên ứng dụng Android. Với API Odoo RPC, bạn có thể thực hiện bất kỳ hoạt động CRUD (tạo, đọc, cập nhật, xoá) nào trên cơ sở dữ liệu. Odoo RPC không giới hạn hoạt động của CRUD; bạn cũng có thể gọi các phương thức công khai của bất kỳ model nào. Tất nhiên, bạn sẽ cần phải tuân theo quy tắc bảo mật của các bản ghi. Odoo RPC không phụ thuộc vào nền tảng, vì vậy bạn có thể sử dụng nó trên bất kỳ nền tảng nào. Odoo RPC có thể được sử dụng với bất kỳ ngôn ngữ lập trình nào, vì vậy bạn có thể tích hợp Odoo với bất kỳ ứng dụng bên ngoài.

Odoo cung cấp hai loại API RPC: XML-RPC và JSON-RPC. Trong phần này, chúng ta sẽ học cách sử dụng các API RPC này từ một chương trình bên ngoài. Cuối cùng, bạn sẽ học cách sử dụng Odoo RPC của thư viện odoorpc OCA.

Trong phần này, sẽ trình bày các nội dung sau:

  • Đăng nhập/ kết nối Odoo bằng XML-RPC.

  • Tìm kiếm/ đọc bản ghi bằng XML-RPC.

  • Tạo/ cập nhật/ xóa bản ghi bằng XML-RPC.

  • Gọi các phương thức bằng XML-RPC.

  • Đăng nhập/ kết nối Odoo bằng JSON-RPC.

  • Tìm kiếm/ đọc bản ghi bằng JSON-RPC.

  • Tạo/ cập nhật/ xóa bản ghi bằng JSON-RPC.

  • Gọi các phương thức bằng JSON-RPC.

  • Thư viện odoorpc OCA.

  • Tạo khóa API.

Yêu cầu kỹ thuật

Trong phần này, chúng ta sẽ sử dụng module viin_education, viin_education_admission đã tạo trong các phần trước. Bạn có thể tìm thấy module viin_education, viin_education_admission trên GitHub: https://github.com/Viindoo/education. Ở đây, chúng ta sẽ không giới thiệu một ngôn ngữ mới vì bạn có thể chưa quen với nó. Chúng ta sẽ tiếp tục sử dụng Python. Bạn có thể sử dụng ngôn ngữ khác nếu muốn, cách làm tương tự.

Để kết nối Odoo bằng RPC, bạn sẽ cần một instance Odoo đang chạy. Trong suốt phần này, chúng ta sẽ giả định rằng bạn có instance Odoo đang chạy trên http://localhost:8069, cơ sở dữ liệu viin_education và bạn đã cài đặt module viin_education, viin_education_admission. .. note:

Bạn  thể kết nối bất kỳ IP hoặc miền hợp lệ nào bằng RPC.  dụ viindoo.com

Đăng nhập/ kết nối Odoo với XML-RPC

Trong phần này, chúng ta sẽ thực hiện xác thực người dùng bằng RPC để kiểm tra xem thông tin xác thực có hợp lệ hay không.

Chuẩn bị

Để kết nối một instance Odoo bằng RPC, bạn sẽ cần một instance Odoo đang chạy để kết nối. Chúng ta giả định rằng bạn có instance Odoo đang chạy trên http://localhost:8069 và bạn đã cài đặt module viin_education.

Các bước thực hiện

Thực hiện các bước sau để thực hiện xác thực người dùng bằng RPC:

  1. Tạo tệp odoo_authenticate.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

from xmlrpc import client

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
common = client.ServerProxy('%s/xmlrpc/2/common' %server_url)
user_id = common.authenticate(db_name, username,password, {})
if user_id:
    print("Success: User id is", user_id)
else:
    print("Failed: wrong credentials")
  1. Chạy tập lệnh Python sau từ Terminal:

>>> python3 odoo_authenticate.py

Lệnh trên sẽ in thông báo thành công cùng với ID người dùng nếu bạn cung cấp thông tin đăng nhập hợp lệ.

Chi tiết

Trong phần này, chúng ta đã sử dụng thư viện Python xmlrpc để kết nối đến instance Odoo thông qua XML-RPC. Đây là một thư viện Python tiêu chuẩn và bạn không phải cài đặt bất kỳ thứ gì khác để sử dụng nó.

Để xác thực, Odoo cung cấp XML-RPC với điểm cuối /xmlrpc/2/common. Điểm cuối này được sử dụng cho các phương thức meta, việc này không yêu cầu xác thực. Bản thân phương thức authenticate() là một phương thức công khai, vì vậy nó có thể được gọi công khai. Phương thức authenticate() chấp nhận bốn đối số: tên cơ sở dữ liệu, tên người dùng, mật khẩu và môi trường tác nhân người dùng. Môi trường tác nhân người dùng là một đối số bắt buộc, nhưng nếu bạn không muốn truyền tham số này thì hãy truyền 1 dictionary rỗng {}.

Khi bạn thực thi phương thức authenticate() với tất cả các đối số hợp lệ, nó sẽ thực hiện cuộc gọi đến máy chủ Odoo và thực hiện xác thực. Sau đó, nó sẽ trả về ID người dùng, miễn là thông tin đăng nhập hợp lệ. Nó sẽ trả về False nếu thông tin đăng nhập không chính xác.

Bạn cần sử dụng phương thức authenticate() trước khi truy cập bất kỳ dữ liệu nào thông qua RPC. Điều này là do sau khi đăng nhập thành công, máy chủ sẽ lưu 1 chứng chỉ đăng nhập. Ở các request sau đó, máy khách sẽ gửi kèm chứng chỉ đăng nhập này, máy chủ sẽ sử dụng nó để xác thực.

Ghi chú

Các instance trực tuyến của Viindoo (.viindoo.com) sử dụng xác thực OAuth, do đó mật khẩu không được tự động sinh ra. Bạn cần đặt mật khẩu thủ công bằng cách: **Cài đặt > menu người dùng & công ty > người dùng > chọn người dùng cần đổi mật khẩu > Nhấn nút hành động > chọn đổi mật khẩu > nhập mật khẩu mới > nhấn đổi mật khẩu*.

Mở rộng

Điểm cuối /xmlrpc/2/common cung cấp thêm phương thức: version(). Bạn có thể gọi phương thức này mà không cần chứng chỉ đăng nhập. Nó sẽ trả về thông tin phiên bản của instance Odoo. Sau đây là một ví dụ về cách sử dụng phương thức version():

from xmlrpc import client
server_url = 'http://localhost:8069'
common = client.ServerProxy('%s/xmlrpc/2/common' %server_url)
version_info = common.version()
print(version_info)

Chương trình sẽ tạo ra kết quả sau:

Đầu ra của chương trình thông tin phiên bản

Chương trình này sẽ in thông tin phiên bản dựa trên máy chủ của bạn.

Tìm kiếm/đọc bản ghi thông qua XML-RPC

Trong phần này, chúng ta sẽ đọc dữ liệu từ một instance Odoo thông qua RPC. Người dùng có thể truy cập hầu hết dữ liệu, ngoại trừ dữ liệu bị hạn chế bởi các quy tắc bảo mật. RPC có thể được sử dụng trong nhiều trường hợp, chẳng hạn như thu thập dữ liệu để phân tích, xử lý nhiều dữ liệu cùng một lúc hoặc tìm kiếm/đọc dữ liệu để hiển thị trong một phần mềm/hệ thống khác. Có vô số khả năng và bạn có thể sử dụng RPC bất cứ khi nào cần thiết.

Chuẩn bị

Chúng ta sẽ tạo một chương trình Python để đọc dữ liệu học sinh từ model education.student. Đảm bảo rằng bạn đã cài đặt module viin_education và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để đọc thông tin của học sinh thông qua RPC:

  1. Tạo file student_data.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

from xmlrpc import client

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
common = client.ServerProxy('%s/xmlrpc/2/common' %server_url)
user_id = common.authenticate(db_name, username, password, {})
models = client.ServerProxy('%s/xmlrpc/2/object' %server_url)
if user_id:
    search_domain = ['|', ['name', 'ilike', 'Hank'], ['name', 'ilike', 'David']]

    # search students
    students_ids = models.execute_kw(db_name, user_id, password, 'education.student', 'search',
                                    [search_domain],{'limit': 5})
    print('Student ids found:', students_ids)

    # read data students
    students_data = models.execute_kw(db_name, user_id, password, 'education.student',
                                    'read', [students_ids, ['name', 'email']])
    print("Students data:", students_data)
else:
    print('Wrong credentials')
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 student_data.py

Chương trình sẽ tìm và đọc dữ liệu của các học sinh và hiển thị kết quả sau:

../../_images/students_data.png

Kết quả hiển thị trong ảnh trên dựa trên dữ liệu trong cơ sở dữ liệu của tôi. Dữ liệu trong instance Odoo của bạn có thể là dữ liệu khác nhau, do đó kết quả đầu ra cũng sẽ khác.

Chi tiết

Để truy cập dữ liệu học sinh, trước tiên bạn phải thực hiện xác thực. Ở phần đầu của chương trình, chúng ta đã thực hiện xác thực theo cách tương tự như chúng ta đã làm trong Đăng nhập/kết nối Odoo với XML-RPC trước đó. Nếu bạn đã cung cấp thông tin xác thực hợp lệ, phương thức authentication() sẽ trả về ID người dùng. Chúng ta sẽ sử dụng ID người dùng này để lấy dữ liệu học sinh.

Điểm cuối /xmlrpc/2/object được sử dụng cho việc đọc cơ sở dữ liệu. Trong đoạn code trên, chúng ta đã sử dụng điểm cuối object để lấy dữ liệu học sinh. Khác với điểm cuối /xmlrpc/2/common, điểm cuối này sẽ không hoạt động nếu không có thông tin xác thực. Với điểm cuối này bạn có thể truy cập các phương thức công khai của bất kỳ model nào thông qua phương thức execute_kw(). execute_kw() nhận các đối số sau:

  • Tên cơ sở dữ liệu.

  • Id người dùng (user_id) (chúng ta có được từ phương thức authenticate()).

  • Mật khẩu.

  • Tên model, ví dụ res.partner hoặc education.student.

  • Tên phương thức, ví dụ: search, read, create.

  • Một mảng chứa các điều kiện, ở ví dụ trên là 1 danh sách id.

  • Một danh sách chứa tên các trường trả về (tuỳ chọn).

Trong ví dụ của chúng ta, chúng ta muốn lấy thông tin của học sinh. Điều này có thể được thực hiện thông qua sự kết hợp của search()read(). Thông tin học sinh được lưu trữ trong education.student, vì vậy trong execute_kw(), chúng ta sử dụng education.student làm model và search làm phương thức. Thao tác này sẽ gọi phương thức search của ORM và trả về ID của các bản ghi. Sự khác biệt duy nhất ở đây là phương thức search của ORM trả về một tập hợp bản ghi, trong khi phương thức search RPC trả về một danh sách các ID.

Trong execute_kw(), bạn có thể truyền các đối số và đối số từ khóa cho phương thức. Phương thức search chấp nhận một domain làm đối số, vì vậy chúng ta đã truyền vào 1 domain để lọc các học sinh. Phương thức search có các đối số khác, chẳng hạn như limit, offset, count, order. Ở ví dụ trên chúng ta đã sử dụng tham số limit để chỉ tìm kiếm năm bản ghi. Thao tác này sẽ trả về danh sách ID học sinh có tên chứa chuỗi 'Hank' hoặc 'David'.

Tuy nhiên, chúng ta cần lấy dữ liệu học sinh từ cơ sở dữ liệu. Chúng ta sử dụng phương thức read để làm điều này. Phương thức read chấp nhận một danh sách các ID và tập các trường. Ở cuối bước 3, chúng ta đã sử dụng danh sách ID học sinh mà chúng ta nhận được từ phương thức search, sau đó sử dụng ID học sinh để lấy name và email của học sinh. Máy chủ sẽ trả về 1 danh sách dictionary chứa thông tin của các học sinh.

Ghi chú

Lưu ý rằng các đối số và đối số từ khóa được truyền trong execute_kw() dựa trên phương thức.

Bạn có thể sử dụng bất kỳ phương thức ORM công khai nào. Bạn chỉ cần cung cấp tên phương thức, các đối số hợp lệ và các đối số từ khóa. Các đối số này được truyền vào phương thức trong ORM.

Mở rộng

Dữ liệu được lấy thông qua sự kết hợp của các phương thức search()read() hơi tốn thời gian vì nó sẽ thực hiện hai cuộc gọi. search_read là một phương thức thay thế để lấy dữ liệu. Bạn có thể tìm kiếm và lấy dữ liệu trong một cuộc gọi. Đây là cách thay thế để lấy dữ liệu của học sinh bằng search_read().

from xmlrpc import client

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
common = client.ServerProxy('%s/xmlrpc/2/common' %server_url)
user_id = common.authenticate(db_name, username,password, {})
models = client.ServerProxy('%s/xmlrpc/2/object' %server_url)
if user_id:
    search_domain = ['|', ['name', 'ilike', 'Hank'],['name', 'ilike', 'David']]
    students_ids = models.execute_kw(db_name, user_id, password,'education.student',  'search_read',
                                    [search_domain, ['name', 'email']],  {'limit': 5})
    print('Students data:', students_ids)
else:
    print('Wrong credentials')

Phương thức search_read cải thiện hiệu suất đáng kể khi bạn nhận được kết quả trong một lần gọi RPC, vì vậy hãy sử dụng phương thức search_read thay vì kết hợp các phương thức searchread.

Tạo/Cập nhật/xoá (CRUD) các bản ghi bằng XML-RPC

Trong phần trước, chúng ta đã biết cách tìm kiếm và đọc dữ liệu thông qua RPC. Trong phần này, chúng ta sẽ thực hiện các hoạt động CRUD (tạo, cập nhật, xoá) còn lại thông qua RPC.

Chuẩn bị

Chúng ta sẽ tạo chương trình Python để tạo, cập nhật và xoá dữ liệu trên model education.student. Đảm bảo rằng bạn đã cài đặt module viin_education và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để tạo, cập nhật và xoá thông tin của học sinh thông qua RPC:

  1. Tạo file students_operation.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

from xmlrpc import client

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
common = client.ServerProxy('%s/xmlrpc/2/common' % server_url)
user_id = common.authenticate(db_name, username, password, {})
models = client.ServerProxy('%s/xmlrpc/2/object' % server_url)
if user_id:
    # create new students
    create_data = [{'name': 'Sutdent 1', 'email': 'student1@example.com'},
                {'name': 'Sutdent 2', 'email': 'student2@example.com'},
                {'name': 'Sutdent 3', 'email': 'student3@example.com'},
                {'name': 'Sutdent 4', 'email': 'student4@example.com'}]
    students_ids = models.execute_kw(
        db_name, user_id, password, 'education.student', 'create', [create_data])
    print("Students created:", students_ids)
    # Write in existing student record
    student_to_write = students_ids[1]  # We will use ids of
    # recently created students
    write_data = {'name': 'Student write'}
    written = models.execute_kw(db_name, user_id, password, 'education.student', 'write', [
                                student_to_write, write_data])
    print("Student written:", written)

    # Delete the student record
    students_to_delete = students_ids[2:]  # We will use ids
    # of recently created students
    deleted = models.execute_kw(
        db_name, user_id, password, 'education.student', 'unlink', [students_to_delete])
    print('Student unlinked:', deleted)
else:
    print('Wrong credentials')
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 students_operation.py

Chương trình trên sẽ tạo bốn bản ghi của học sinh. Cập nhật dữ liệu trong các bản ghi học sinh và sau đó xóa hai bản ghi. Chương trình sẽ đưa ra kết quả như sau (các ID được tạo có thể khác nhau tùy thuộc vào cơ sở dữ liệu của bạn):

../../_images/students_operation.png

Phương thức writeunlink trả về True nếu thao tác thành công. Điều này có nghĩa là nếu bạn nhận được True trong response, một bản ghi đã được cập nhật hoặc xóa thành công.

Chi tiết

Trong phần này, chúng ta đã thực hiện các thao tác tạo, cập nhật và xóa thông qua XML-RPC. Thao tác này cũng sử dụng điểm cuối /xmlrpc/2/object và phương thức execute_kw().

Phương thức create hỗ trợ tạo nhiều bản ghi trong một lần gọi. Ở ví dụ trên, đầu tiên chúng ta tạo một dictionary với thông tin của học sinh. Sau đó, chúng ta sử dụng dictionary của học sinh để tạo các bản ghi mới thông qua XML-RPC. Lệnh gọi XML-RPC cần hai tham số để tạo bản ghi mới: tên phương thức create và dữ liệu học sinh. Thao tác này sẽ tạo bốn bản ghi học sinh trong model education.student. Trong ORM, khi bạn tạo bản ghi, nó trả về một tập hợp bản ghi gồm các bản ghi đã tạo, nhưng nếu bạn sử dụng RPC sẽ trả về một danh sách các ID.

Phương thức write hoạt động tương tự như phương thức create. Phương thức write cần phải truyền một danh sách các ID của bản ghi và dictionary chứa các cặp field-value. Ở bước 2, chúng ta đã cập nhật tên của học sinh được tạo ở phần đầu tiên. Thao tác này sẽ cập nhật tên của học sinh thứ hai từ Student 2 thành Student write. Ở đây, chúng ta chỉ truyền một id của học sinh, bạn có thể truyền danh sách ID nếu bạn muốn cập nhật nhiều bản ghi trong một lần gọi.

Ở phần thứ ba của chương trình, chúng ta đã xóa hai học sinh mà chúng ta đã tạo. Bạn có thể xóa bản ghi bằng phương thức unlink. Tham số truyền vào là danh sách ID của các bản ghi.

Sau khi chương trình được thực thi thành công, bạn sẽ tìm thấy hai bản học sinh trong cơ sở dữ liệu, như được chỉ ra trong hình trên. Trong chương trình, chúng ta đã tạo bốn bản ghi, nhưng chúng ta cũng đã xóa hai bản ghi trong số đó, vì vậy bạn sẽ chỉ tìm thấy hai bản ghi mới trong cơ sở dữ liệu.

Mở rộng

Khi bạn đang thực hiện thao tác CRUD thông qua RPC, điều này có thể tạo ra lỗi nếu bạn không có quyền thực hiện thao tác đó. Với phương thức check_access_rights, bạn có thể kiểm tra xem người dùng có quyền truy cập thích hợp để thực hiện một thao tác nhất định hay không. Phương thức check_access_rights trả về giá trị True hoặc False dựa trên quyền truy cập của người dùng. Dưới đây là một ví dụ cho thấy liệu người dùng có quyền tạo bản ghi học sinh hay không:

from xmlrpc import client

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
common = client.ServerProxy('%s/xmlrpc/2/common' % server_url)
user_id = common.authenticate(db_name, username, password, {})
models = client.ServerProxy('%s/xmlrpc/2/object' % server_url)
if user_id:
    has_access = models.execute_kw(db_name, user_id,
                                password,
                                'education.student', 'check_access_rights',
                                ['create'], {'raise_exception': False})
    print('Has create access on students:', has_access)
else:
    print('Wrong credentials')
# Output: Has create access on students: True

Khi bạn thực hiện các cuộc gọi phức tạp thông qua RPC, phương thức check_access_rights có thể được sử dụng trước khi thực hiện thao tác để đảm bảo bạn có quyền truy cập thích hợp.

Gọi các phương thức thông qua XML-RPC

Với Odoo, API RPC không chỉ giới hạn đối với các hoạt động CRUD; bạn có thể gọi các phương thức công khai của model. Trong phần này, chúng ta sẽ gọi phương thức action_confirm để thay đổi trạng thái của hồ sơ tuyển sinh.

Chuẩn bị

Chúng ta sẽ tạo chương trình Python để gọi phương thức action_confirm của model education.application. Đảm bảo rằng bạn đã cài đặt module viin_education_admission và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để gọi phương thức action_confirm của model education.application:

  1. Tạo file application_method.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

from xmlrpc import client

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
common = client.ServerProxy('%s/xmlrpc/2/common' % server_url)
user_id = common.authenticate(db_name, username, password, {})
models = client.ServerProxy('%s/xmlrpc/2/object' % server_url)
if user_id:
    # Create application with state draft
    application_id = models.execute_kw(db_name, user_id, password,
                                    'education.application', 'create',
                                    [{'name': 'New application', 'application_date': '2022-01-18', 'admission_date': '2022-01-18', 'state': 'draft'}])
    # Call action_confirm method on new application
    models.execute_kw(db_name, user_id, password,
                    'education.application', 'action_confirm', [[application_id]])
    # check application status after method call
    application_data = models.execute_kw(db_name, user_id, password,
                                        'education.application', 'read', [[application_id], ['name', 'state']])
    print('Student state after method call:', application_data[0]['state'])
else:
    print('Wrong credentials')
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 application_method.py

Chương trình sẽ tạo một hồ sơ tuyển sinh có trạng thái dự thảo và sau đó chúng ta sẽ thay đổi trạng thái của hồ sơ tuyển sinh bằng cách gọi phương thức action_confirm. Sau đó, chúng ta sẽ đọc dữ liệu hồ sơ tuyển sinh để kiểm tra trạng thái của hồ sơ tuyển sinh, điều này sẽ tạo ra kết quả sau:

../../_images/application_method.png

Chương trình sẽ tạo một bản ghi mới và thay đổi trạng thái của hồ sơ tuyển sinh bằng cách gọi phương thức của model. Đến cuối chương trình, chúng ta đã đọc bản ghi hồ sơ tuyển sinh và in trạng thái của nó.

Chi tiết

Trong ví dụ của chúng ta, chúng ta đã tạo một hồ sơ tuyển sinh có trạng thái là dự thảo. Sau đó, chúng ta thực hiện thêm một cuộc gọi RPC để gọi phương thức action_confirm, phương thức này sẽ thay đổi trạng thái của hồ sơ tuyển sinh thành xác nhận. Cuối cùng, chúng ta đã thực hiện thêm một cuộc gọi RPC để kiểm tra trạng thái của hồ sơ tuyển sinh. Trạng thái của hồ sơ tuyển sinh đã thay đổi thành xác nhận, như được chỉ ra trong hình.

Bạn có thể gọi bất kỳ phương thức công khai của model bằng RPC. Điều này giúp bạn thực hiện logic nghiệp vụ mà không gặp phải cản chở. Ví dụ: bạn đã tạo đơn đặt hàng từ RPC và sau đó gọi phương thức action_confirm của model sale.order. Điều này tương đương với việc nhấp vào nút Xác nhận trên đơn đặt hàng của sale.order.

Bạn có thể gọi bất kỳ phương thức công khai của model, nhưng bạn không thể gọi một phương thức private bằng RPC. Tên phương thức bắt đầu bằng _ được gọi là phương thức private, chẳng hạn như _get_share_url()_get_data().

Sẽ an toàn khi sử dụng các phương thức này vì chúng đi qua ORM và tuân theo tất cả các quy tắc bảo mật. Nếu phương thức đang truy cập các bản ghi trái phép, nó sẽ tạo ra lỗi.

Các phương thức không trả về bất kỳ thứ gì sẽ trả về None theo mặc định. Các phương thức này không thể được sử dụng từ RPC. Do đó, nếu bạn muốn sử dụng phương thức của mình từ RPC, ít nhất hãy thêm return True.

Mở rộng

Nếu một ngoại lệ được tạo ra từ một phương thức, tất cả các thao tác được thực hiện trong phiên sẽ được tự động quay trở lại trạng thái ban đầu. Điều này chỉ áp dụng cho một cuộc gọi duy nhất. Ví dụ, hãy tưởng tượng bạn đang thực hiện hai cuộc gọi RPC đến máy chủ và có một ngoại lệ được tạo ra trong cuộc gọi thứ hai. Thao tác này sẽ khôi phục hoạt động được thực hiện trong lần gọi RPC thứ hai. Thao tác được thực hiện thông qua cuộc gọi RPC đầu tiên sẽ không được khôi phục. Do đó, bạn muốn thực hiện một hoạt động phức tạp thông qua RPC. Bạn nên thực hiện điều này trong một lệnh gọi RPC bằng cách tạo một phương thức trong model.

Đăng nhập/kết nối Odoo với JSON-RPC

Odoo cung cấp thêm một loại API RPC: JSON-RPC. Như tên gọi của nó, JSON-RPC hoạt động ở định dạng JSON và sử dụng đặc điểm kỹ thuật jsonrpc 2.0. Trong phần này, chúng ta sẽ xem cách bạn có thể đăng nhập bằng JSON-RPC. Bản thân ứng dụng web Odoo sử dụng JSON-RPC để dữ liệu từ máy chủ.

Chuẩn bị

Trong phần này, chúng ta sẽ thực hiện xác thực người dùng thông qua JSON-RPC để kiểm tra xem thông tin xác thực đã cho có hợp lệ hay không. Đảm bảo rằng bạn đã cài đặt module viin_education và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để thực hiện xác thực người dùng thông qua RPC:

  1. Tạo file jsonrpc_authenticate.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

import json
import random
import requests

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })


payload = get_json_payload("common", "login", db_name, username, password)
response = requests.post(json_endpoint, data=payload, headers=headers)
user_id = response.json()['result']
if user_id:
    print("Success: User id is", user_id)
else:
print("Failed: wrong credentials")
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 jsonrpc_authenticate.py

Khi bạn chạy chương trình trước đó với thông tin đăng nhập hợp lệ, chương trình sẽ in thông báo thành công với id của người dùng, như sau:

../../_images/jsonrpc_authenticate.png

Xác thực JSON hoạt động giống như XML-RPC, nhưng nó trả về một kết quả ở định dạng JSON.

Chi tiết

JSON-RPC sử dụng định dạng JSON để giao tiếp với máy chủ bằng cách sử dụng điểm cuối /jsonrpc. Trong ví dụ, chúng ta đã sử dụng gói requests của Python để thực hiện request POST. Nhưng nếu muốn, bạn có thể sử dụng các gói khác, chẳng hạn như urllib.

JSON-RPC chỉ chấp nhận payload được định dạng trong đặc tả JSON-RPC 2.0. Bạn có thể tìm hiểu thêm về định dạng JSON-RPC tại đây: https://www.jsonrpc.org/specification. Trong ví dụ, chúng ta đã tạo phương thức get_json_payload(). Phương thức này sẽ chuẩn bị payload có định dạng JSON-RPC 2.0 hợp lệ. Phương thức này có các đối số truyền vào: service, method và các đối số còn lại sẽ được đặt trong *args. JSON-RPC chấp nhận các request có định dạng JSON, các request này chỉ được chấp nhận khi headers là {"Content-Type": "application / json"}. Kết quả trả về sẽ có dạng JSON.

Giống như XML-RPC, tất cả các phương thức công khai, bao gồm cả đăng nhập đều thuộc common service. Vì lý do này, chúng ta đã truyền common vào đối số servicelogin vào method để chuẩn bị payload JSON. Phương thức đăng nhập yêu cầu thêm các đối số bổ sung, vì vậy chúng ta đã truyền tên cơ sở dữ liệu, tên người dùng và mật khẩu. Sau đó, chúng ta thực hiện request đăng nhập tới điểm cuối JSON với payload và headers. Nếu bạn đã nhập đúng tên người dùng và mật khẩu, phương thức này sẽ trả về ID người dùng. Kết quả trả về có định dạng JSON, ID người dùng nằm trong khoá result.

Mở rộng

Giống như XML-RPC, phương thức version() cũng có sẵn trong JSON-RPC. Phương thức version() này thuộc common service và có thể truy cập công khai. Bạn có thể nhận thông tin phiên bản mà không cần chứng chỉ đăng nhập. Xem ví dụ sau cho thấy cách lấy thông tin phiên bản của máy chủ Odoo:

import json
import random
import requests
server_url = 'http://localhost:8069'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })
payload = get_json_payload("common", "version")
response = requests.post(json_endpoint, data=payload, headers=headers)
print(response.json())

Chương trình sẽ hiển thị thông tin phiên bản của máy chủ.

Tìm kiếm/ đọc bản ghi bằng JSON-RPC

Trong phần trước, chúng ta đã biết cách thực hiện xác thực thông qua JSON-RPC. Trong phần này, chúng ta sẽ xem cách tìm kiếm dữ liệu từ instance Odoo với JSON-RPC.

Chuẩn bị

Trong phần này, chúng ta sẽ tìm kiếm thông tin application bằng JSON-RPC. Đảm bảo rằng bạn đã cài đặt module viin_education_admission và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để tìm kiếm/đọc dữ liệu học sinh từ model education.student:

  1. Tạo file jsonrpc_fetch_data.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

import json
import random
import requests

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })


payload = get_json_payload("common", "login", db_name, username, password)
response = requests.post(json_endpoint, data=payload, headers=headers)
user_id = response.json()['result']

if user_id:
    # search for the student's ids
    search_domain = ['|', ['name', 'ilike', 'Hank'],
                    ['name', 'ilike', 'David']]
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password,
                            'education.student', 'search',
                            [search_domain], {'limit': 5})
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    print('Search Result:', res)
    # ids will be in result keys
    # read data for application ids
    payload = get_json_payload("object", "execute_kw", db_name, user_id, password,
                            'education.student', 'read', [res['result'], ['name', 'email']])
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    print('Students data:', res)
else:
    print("Failed: wrong credentials")
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 jsonrpc_fetch_data.py

Chương trình trên sẽ trả về kết quả sau. Lệnh gọi RPC đầu tiên sẽ in ID của học sinh và lệnh thứ hai sẽ in thông tin cho ID của học sinh:

../../_images/jsonrpc_fetch_data.png

Kết quả hiển thị trong ảnh chụp màn hình trước dựa trên dữ liệu trong cơ sở dữ liệu của tôi. Dữ liệu trong instance Odoo của bạn có thể là dữ liệu khác nhau, do đó kết quả đầu ra cũng sẽ khác.

Chi tiết

Trong phần Đăng nhập/kết nối Odoo bằng JSON-RPC, chúng ta thấy rằng bạn có thể xác thực tên người dùng và mật khẩu. Nếu thông tin đăng nhập chính xác, lệnh gọi RPC sẽ trả về ID người dùng. Sau đó, bạn có thể sử dụng ID người dùng này để lấy dữ liệu của model. Giống như XML-RPC, chúng ta cần sử dụng kết hợp searchread để lấy dữ liệu từ model. Để lấy dữ liệu, chúng ta sử dụng object làm đối số serviceexecute_kw() làm method. execute_ kw() là phương thức mà chúng ta đã sử dụng trong XML-RPC, nó chấp nhận cùng đối số như sau:

  • Tên cơ sở dữ liệu.

  • Id người dùng (user_id) (chúng ta có được từ phương thức authenticate()).

  • Mật khẩu.

  • Tên model, ví dụ res.partner hoặc education.student.

  • Tên phương thức, ví dụ: search, read, create.

  • Một mảng chứa các điều kiện, ở ví dụ trên là 1 danh sách id.

  • Một danh sách chứa tên các trường trả về (tuỳ chọn).

Trong ví dụ, chúng ta đã gọi phương thức search đầu tiên. Trong phương thức search, domain là đối số bắt buộc, vì vậy chúng ta đã truyền nó vào đối số bắt buộc và truyền đối số tùy chọn limit vào đối số từ khóa (kiểu dictionary). Bạn sẽ nhận được response ở định dạng JSON và trong phần này, response của phương thức search RPC sẽ có danh sách ID của học sinh trong khóa result.

Trong bước 2, chúng ta đã thực hiện một cuộc gọi RPC với phương thức read. Để đọc thông tin của học sinh, chúng ta đã truyền hai đối số cố định: danh sách ID học sinh và danh sách các trường cần lấy. Lệnh gọi RPC này sẽ trả về thông tin học sinh ở định dạng JSON và bạn có thể truy cập thông tin đó trong khóa result.

Ghi chú

Thay vì execute_kw(), bạn có thể sử dụng execute làm method. execute không hỗ trợ các đối số từ khóa, vì vậy bạn cần phải truyền tất cả các đối số cố định sau đó đến đối số tuỳ chọn.

Mở rộng

Tương tự như XML-RPC, bạn có thể sử dụng phương thức search_read thay vì tổ hợp phương thức searchread vì nó hơi tốn thời gian. Hãy xem đoạn mã sau:

import json
import random
import requests

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })


payload = get_json_payload("common", "login", db_name, username, password)
response = requests.post(json_endpoint, data=payload, headers=headers)
user_id = response.json()['result']

if user_id:
    # search for the student's ids
    search_domain = ['|', ['name', 'ilike', 'Hank'],
                    ['name', 'ilike', 'David']]
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password,
                            'education.student', 'search_read',
                            [search_domain,  ['name', 'email']], {'limit': 5})
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    print('Students data:', res)
else:
    print("Failed: wrong credentials")

Đoạn mã là một cách thay thế để lấy dữ liệu sách bằng search_read. Nó sẽ trả về kết quả giống như trong ví dụ trước.

Tạo/Cập nhật/xoá (CRUD) các bản ghi bằng JSON-RPC

Trong phần trước, chúng ta đã biết cách tìm kiếm và đọc dữ liệu thông qua JSON-RPC. Trong phần này, chúng ta sẽ thực hiện các hoạt động CRUD (tạo, cập nhật, xoá) còn lại thông qua JSON-RPC.

Chuẩn bị

Chúng ta sẽ tạo chương trình Python để tạo, cập nhật và xoá dữ liệu trên model education.student. Đảm bảo rằng bạn đã cài đặt module viin_education và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để tạo, cập nhật và xoá thông tin của học sinh thông qua JSON-RPC:

  1. Tạo file jsonrpc_operation.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

import json
import random
import requests

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })


payload = get_json_payload("common", "login", db_name, username, password)
response = requests.post(json_endpoint, data=payload, headers=headers)
user_id = response.json()['result']

if user_id:
    # create new students
    create_data = [{'name': 'Sutdent 1', 'email': 'student1@example.com'},
                {'name': 'Sutdent 2', 'email': 'student2@example.com'},
                {'name': 'Sutdent 3', 'email': 'student3@example.com'},
                {'name': 'Sutdent 4', 'email': 'student4@example.com'}]
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password, 'education.student',
                            'create', [create_data])
    res = requests.post(json_endpoint, data=payload, headers=headers).json()
    print("Students created:", res)
    students_ids = res['result']
    # Write in existing student record
    student_to_write = students_ids[1]
    # We will use ids of recently created students
    write_data = {'name': 'Student 2'}
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password, 'education.student',
                            'write', [student_to_write, write_data])
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    print("Students written:", res)
    # Delete in existing student record
    student_to_unlink = students_ids[2:]
    # We will use ids of recently created students
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password, 'education.student',
                            'unlink', [student_to_unlink])
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    print("Students deleted:", res)
else:
    print("Failed: wrong credentials")
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 jsonrpc_operation.py

Chương trình trước trên sẽ tạo bốn bản ghi của học sinh. Cập nhật dữ liệu trong các bản ghi học sinh và sau đó xóa hai bản ghi. Chương trình sẽ đưa ra kết quả như sau (các ID được tạo có thể khác nhau tùy thuộc vào cơ sở dữ liệu của bạn):

../../_images/jsonrpc_operation.png

Phương thức writeunlink trả về True nếu thao tác thành công. Điều này có nghĩa là nếu bạn nhận được True trong response, một bản ghi đã được cập nhật hoặc xóa thành công.

Chi tiết

execute_kw được sử dụng cho các hoạt động tạo, cập nhật và xóa. Từ Odoo phiên bản 12, phương thức create hỗ trợ tạo nhiều bản ghi. Vì vậy, chúng ta đã chuẩn bị 1 list các dictionary với thông tin của bốn học sinh. Sau đó, chúng ta thực hiện cuộc gọi JSON-RPC với education.student làm tên model và create làm tên phương thức. Thao tác này sẽ tạo bốn bản ghi học sinh trong cơ sở dữ liệu và trả về response JSON với ID của những học sinh mới được tạo. Trong các lệnh gọi RPC tiếp theo, chúng ta sử dụng các ID này để thực hiện lệnh gọi RPC cho các phương thức writeunlink, vì vậy chúng ta gán nó cho biến students_ids.

Ghi chú

Cả JSON-RPC và XML-RPC đều tạo ra lỗi khi bạn cố gắng tạo bản ghi mà không cung cấp giá trị cho trường bắt buộc, vì vậy hãy đảm bảo rằng bạn đã thêm tất cả giá trị cho trường bắt buộc.

Trong lần gọi RPC tiếp theo, chúng ta đã sử dụng phương thức write để cập nhật các bản ghi hiện có. Phương thức write chấp nhận hai đối số cố định: danh sách id của các bản ghi và các cặp key-value. Trong ví dụ, chúng ta đã cập nhật tên học sinh bằng cách sử dụng ID của học sinh thứ hai. Thao tác này sẽ thay đổi tên của học sinh thứ hai từ Student 2 thành Student write.

Sau đó, chúng ta thực hiện cuộc gọi RPC cuối cùng để xóa hai hồ sơ sổ học sinh. Để làm như vậy, chúng ta đã sử dụng phương thức unlink. Phương thức unlink kết chỉ chấp nhận một đối số, đó là ID của bản ghi bạn muốn xóa. Lệnh gọi RPC này sẽ xóa hai học sinh cuối cùng.

Mở rộng

Giống như XML-RPC, bạn có thể sử dụng phương thức check_access_rights trong JSON-RPC để kiểm tra xem bạn có quyền truy cập để thực hiện thao tác hay không. Phương thức này yêu cầu hai tham số: tên model và tên hành động. Trong ví dụ sau, chúng ta kiểm tra quyền truy cập cho hoạt động tạo trên model education.student:

import json
import random
import requests

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })


payload = get_json_payload("common", "login", db_name, username, password)
response = requests.post(json_endpoint, data=payload, headers=headers)
user_id = response.json()['result']

if user_id:
    payload = get_json_payload("object", "execute_kw",db_name, user_id, password,
                            'education.student', 'check_access_rights', ['create'])
    res = requests.post(json_endpoint, data=payload, headers=headers).json()
    print("Has create access:", res['result'])
else:
    print("Failed: wrong credentials")

Khi bạn thực hiện các hành động phức tạp thông qua RPC, phương thức check_access_rights có thể được sử dụng trước khi thực hiện thao tác để đảm bảo bạn có quyền truy cập thích hợp.

Gọi các phương thức thông qua JSON-RPC

Trong phần này, chúng ta sẽ gọi phương thức action_confirm để thay đổi trạng thái của hồ sơ tuyển sinh qua JSON-RPC.

Chuẩn bị

Chúng ta sẽ tạo chương trình Python để gọi phương thức action_confirm của model education.application. Đảm bảo rằng bạn đã cài đặt module viin_education_admission và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để tạo, cập nhật và xoá thông tin của học sinh thông qua RPC:

  1. Tạo file jsonrpc_method.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

import json
import random
import requests

server_url = 'http://localhost:8069'
db_name = 'viin_education'
username = 'admin'
password = 'admin'
json_endpoint = "%s/jsonrpc" % server_url
headers = {"Content-Type": "application/json"}


def get_json_payload(service, method, *args):
    return json.dumps({
        "jsonrpc": "2.0",
        "method": 'call',
        "params": {
            "service": service,
            "method": method,
            "args": args
        },
        "id": random.randint(0, 100000000),
    })


payload = get_json_payload("common", "login", db_name, username, password)
response = requests.post(json_endpoint, data=payload, headers=headers)
user_id = response.json()['result']

if user_id:
    # Create the application in draft state
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password,
                            'education.application', 'create',
                            [{'name': 'New application', 'application_date': '2022-01-18', 'admission_date': '2022-01-18', 'state': 'draft'}])
    res = requests.post(json_endpoint, data=payload, headers=headers).json()

    print("Has create success:", res['result'])
    application_id = res['result']
    # Change the application state by calling make_available
    # method
    payload = get_json_payload("object", "execute_kw", db_name, user_id, password,
                            'education.application', 'action_confirm', [application_id])
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    # Check the application status after method call
    payload = get_json_payload("object", "execute_kw",
                            db_name, user_id, password,
                            'education.application', 'read', [application_id, ['name', 'state']])
    res = requests.post(json_endpoint, data=payload,
                        headers=headers).json()
    print("Application state after the method call:", res['result'])
else:
    print("Failed: wrong credentials")
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 jsonrpc_method.py

Lệnh trên sẽ tạo một hồ sơ tuyển sinh có trạng thái dự thảo và sau đó chúng ta sẽ thay đổi trạng thái hồ sơ tuyển sinh bằng cách gọi phương thức action_confirm. Sau đó, chúng ta lấy dữ liệu hồ sơ tuyển sinh để kiểm tra trạng thái của hồ sơ tuyển sinh, điều này sẽ tạo ra kết quả sau:

../../_images/jsonrpc_method.png

Chương trình sẽ tạo một bản ghi hồ sơ tuyển sinh mới và thay đổi trạng thái của hồ sơ tuyển sinh bằng cách gọi phương thức của model. Vào cuối chương trình, chúng ta sẽ đọc hồ sơ tuyển sinh và in trạng thái sau khi cập nhật.

Chi tiết

execute_kw có khả năng gọi bất kỳ phương thức công khai nào của model. Như chúng ta đã thấy trong Gọi các phương thức thông qua XML-RPC, các phương thức công khai là những phương thức có tên không bắt đầu bằng _ (dấu gạch dưới). Các phương thức bắt đầu bằng _ là private và bạn không thể gọi chúng từ JSON-RPC.

Trong ví dụ, chúng ta đã tạo một hồ sơ tuyển sinh với trạng thái là dự thảo. Sau đó, chúng ta thực hiện cuộc gọi RPC để gọi phương thức ''action_confirm'', phương thức này sẽ thay đổi trạng thái của hồ sơ tuyển sinh thành xác nhận. Cuối cùng, chúng ta đã thực hiện thêm một cuộc gọi RPC để kiểm tra trạng thái của hồ sơ tuyển sinh. Điều này sẽ cho thấy rằng trạng thái của hồ sơ tuyển sinh đã thay đổi thành xác nhận, như trong hình.

Các phương thức không trả về bất kỳ thứ gì sẽ trả về None theo mặc định. Các phương thức như vậy không thể được sử dụng từ RPC. Do đó, nếu bạn muốn sử dụng phương thức của mình từ RPC, ít nhất hãy thêm câu lệnh trả về ''True''.

The OCA odoorpc library

Cộng đồng Odoo (OCA) cung cấp một thư viện Python có tên là odoorpc (https://github.com/OCA/odoorpc). Thư viện odoorpc cung cấp cú pháp thân thiện với người dùng để truy cập dữ liệu Odoo thông qua RPC. Nó cung cấp một cú pháp tương tự cho máy chủ. Trong phần này, chúng ta sẽ tìm hiểu cách sử dụng thư viện odoorpc để thực hiện các hoạt động thông qua RPC.

Chuẩn bị

Thư viện odoorpc được đăng ký trên gói Python (PyPI). Để sử dụng thư viện, bạn cần cài đặt nó bằng lệnh sau. Bạn có thể sử dụng điều này trong một môi trường ảo riêng biệt nếu bạn muốn:

pip install OdooRPC

Trong phần này, chúng ta sẽ thực hiện một số thao tác cơ bản bằng thư viện odoorpc. Chúng ta sẽ sử model education.student để thực hiện các hoạt động này. Đảm bảo rằng bạn đã cài đặt module viin_education và máy chủ đang chạy trên http://localhost:8069.

Các bước thực hiện

Thực hiện các bước sau để tạo, cập nhật và xoá thông tin của học sinh thông qua JSON-RPC:

  1. Tạo file odoorpc_library.py. Bạn có thể đặt tệp này ở bất kỳ đâu bạn muốn vì chương trình RPC sẽ hoạt động độc lập.

  2. Thêm mã sau vào tệp:

import odoorpc

db_name = 'viin_education'
user_name = 'admin'
password = 'admin'
# Prepare the connection to the server
odoo = odoorpc.ODOO('localhost', port=8069)
odoo.login(db_name, user_name, password)  # login
# User information
user = odoo.env.user
print(user.name)  # name of the user connected
print(user.company_id.name)
# the name of user's company
print(user.email)  # the email of user
StudentModel = odoo.env['education.student']
ApplicationModel = odoo.env['education.application']
search_domain = ['|', ['name', 'ilike', 'Hank'],
                ['name', 'ilike', 'David']]
students_ids = StudentModel.search(search_domain, limit=5)
print('students_ids= ', students_ids)
for student in StudentModel.browse(students_ids):
    print(student.name, student.email)
# create the application and update the state
application_id = ApplicationModel.create(
    {'name': 'Test application', 'application_date': '2022-01-18', 'admission_date': '2022-01-18', 'state': 'draft'})
application = ApplicationModel.browse(application_id)
application.action_confirm()

application = ApplicationModel.browse(application_id)
print("Application state before action_confirm:", application.state)
  1. Chạy tập lệnh Python từ Terminal bằng lệnh sau:

>>> python3 odoorpc_library.py

Chương trình sẽ thực hiện xác thực, in thông tin người dùng và thực hiện một hoạt động trong model education.application. Nó sẽ tạo ra kết quả sau:

../../_images/odoorpc_library.png

Trong hình trên là kết quả của một số lệnh gọi RPC. Chúng ta đã lấy thông tin người dùng, một số thông tin học sinh và chúng ta đã thay đổi trạng thái hồ sơ tuyển sinh.

Chi tiết

Sau khi cài đặt thư viện odoorpc, bạn có thể bắt đầu sử dụng nó ngay lập tức. Để làm như vậy, bạn sẽ cần import odoorpc và sau đó chúng ta sẽ tạo đối tượng của lớp ODOO bằng cách chuyển URL và port của máy chủ. Thao tác này sẽ thực hiện cuộc gọi /version_info đến máy chủ để kiểm tra kết nối. Để đăng nhập, bạn cần sử dụng phương thức login() của đối tượng odoo. Tại đây, bạn cần truyền tên cơ sở dữ liệu, tên người dùng và mật khẩu.

Sau khi đăng nhập thành công, bạn có thể truy cập thông tin người dùng tại odoo.env.user. Odoorpc cung cấp phiên bản RPC thân thiện với người dùng, vì vậy bạn có thể sử dụng đối tượng người dùng này chính xác như bản ghi được thiết lập trong máy chủ. Trong ví dụ, chúng ta đã truy cập tên, email và tên công ty từ đối tượng người dùng này.

Nếu bạn muốn truy cập tới model, bạn có thể sử dụng odoo.env.object. Bạn có thể gọi bất kỳ phương thức public nào. Về cơ bản, thư viện odoorpc sử dụng jsonrpc, vì vậy bạn không thể gọi bất kỳ tên phương thức private nào (bắt đầu bằng dấu _). Trong ví dụ, chúng ta đã truy cập model education.student. Sau đó, chúng ta gọi phương thức tìm kiếm với các tham số domainlimit. Thao tác này sẽ trả về ID của học sinh. Bằng cách truyền ID học sinh cho phương thức browse, bạn có thể lấy tập hợp bản ghi cho model education.student.

Vào cuối chương trình, chúng ta sẽ tạo một hồ sơ tuyển sinh mới và thay đổi trạng thái của hồ sơ tuyển sinh bằng cách gọi phương thức action_confirm. Nếu bạn quan sát kỹ cú pháp của chương trình, bạn sẽ thấy rằng nó sử dụng cùng một cú pháp với máy chủ.

Mở rộng

Mặc dù odoorpc cung cấp cú pháp thân thiện với người dùng, bạn cũng có thể sử dụng thư viện giống như cú pháp RPC thông thường. Để làm như vậy, bạn cần sử dụng phương thức odoo.execute với tên model, tên phương thức và các đối số. Dưới đây là một ví dụ về cách đọc một số thông tin học sinh trong cú pháp RPC thô:

import odoorpc
db_name = 'viin_education'
user_name = 'admin'
password = 'admin'
# Prepare the connection to the server
odoo = odoorpc.ODOO('localhost', port=8069)
odoo.login(db_name, user_name, password)  # login
books_info = odoo.execute('education.student', 'search_read',
                        [['name', 'ilike', 'Hank']], ['name', 'email'])
print(books_info)

Tham khảo

Có một số triển khai khác của thư viện RPC cho Odoo, như sau:

Tạo khóa API

Odoo v14 có hỗ trợ tích hợp cho tính năng Xác thực hai yếu tố (2FA). 2FA là một lớp bảo mật bổ sung cho tài khoản người dùng và người dùng cần nhập mật khẩu và mã dựa trên thời gian. Nếu bạn đã bật 2FA, thì bạn sẽ không thể sử dụng RPC bằng cách nhập ID người dùng và mật khẩu của mình. Để khắc phục điều này, bạn sẽ cần tạo khóa API cho người dùng. Trong phần này, chúng ta sẽ xem cách bạn có thể tạo khóa API.

Các bước thực hiện

Thực hiện các bước sau để tạo khóa API cho RPC:

  1. Mở tùy chỉnh cá nhân và > mở thẻ bảo mật tài khoản.

  2. Nhấp vào nút Khóa API mới:

../../_images/gender_api_key.vi.png
  1. Sau khi nhấn khoá API mới, có thể hệ thống sẽ mở cửa sổ xác thực. Bạn nhập mật khẩu và tiếp tục

  2. Cửa sổ tạo khoá API được hiện nên như trong hình sau. Bạn nhập tên khóa API và nhấp vào nút Tạo khóa:

../../_images/create_new_api.vi.png
  1. Hệ thống sẽ tạo khoá API và hiển thị trong cửa sổ mới như hình dưới. Lưu lại khoá API vì bạn sẽ cần nó.

../../_images/api_key.vi.png

Sau khi khóa API được tạo, bạn có thể bắt đầu sử dụng khóa API cho RPC theo cách giống như mật khẩu thông thường.

Chi tiết

Sử dụng khóa API rất đơn giản. Tuy nhiên, có một số điều mà bạn cần phải lưu ý. Các khóa API được tạo cho mỗi người dùng và nếu bạn muốn sử dụng RPC cho nhiều người dùng, bạn sẽ cần tạo khóa API cho từng người dùng. Ngoài ra, khóa API có quyền truy cập giống như thao tác của người dùng, vì vậy nếu ai đó có quyền truy cập vào khóa, họ có thể thực hiện tất cả các thao tác mà người dùng có thể. Vì vậy, bạn cần giữ bí mật khóa API.

Ghi chú

Khi bạn tạo khóa API, khóa này chỉ được hiển thị một lần. Bạn cần lưu lại khóa. Nếu bạn làm mất nó, không có cách nào để lấy lại. Trong những trường hợp như vậy, bạn cần phải xóa khóa API và tạo một khóa mới.

Sử dụng khóa API rất đơn giản. Trong các cuộc gọi RPC, bạn chỉ cần sử dụng khóa API thay vì mật khẩu người dùng. Bạn sẽ có thể gọi RPC ngay cả khi 2FA được kích hoạt.