2016-02-19 16 views
5

Tôi có 3 mô hình có liên quan với nhau với mối quan hệ một-nhiều.Logic kinh doanh ở đâu trong phương thức mô hình đi trong Django Rest Framework?

  • Model A có thể có nhiều trường hợp mẫu B.
  • Model A có thể có nhiều trường hợp mẫu C.
  • Model B có thể có nhiều trường hợp mẫu C.

Ý tưởng là một người dùng sẽ tạo ra một thể hiện của Model A (giống như một danh mục đầu tư chứng khoán) và sau đó nhập cổ phần (Model C). Trường hợp Mô hình B phù hợp là tôi muốn chạy các phép tính/logic dựa trên các cổ phiếu (Mẫu C) trong danh mục (Mẫu A) và sử dụng một lớp/mô hình khác để theo dõi mọi thứ làm cho cuộc sống dễ dàng hơn, do đó Model B.

Tôi ban đầu đã có logic cho các tính toán này trong chế độ xem Django nhưng đọc trong Hai Muỗng của Django rằng logic nghiệp vụ phải được tách riêng khỏi chế độ xem. Kết quả là tôi đã chuyển logic sang phương thức Model A (danh mục đầu tư) và bây giờ gọi phương thức đó từ một khung nhìn. Logic này lặp qua các cổ phiếu và tạo ra các trường hợp mới của Mô hình B, kết quả.

Tôi hiện đang quan tâm đến việc khám phá django-rest-framework để cung cấp API cho giao diện người dùng javascript (như Góc). Tôi đoán rằng tôi sẽ không thể có loại thao tác dữ liệu này trong các giao diện REST của tôi. Tuy nhiên, kết quả của logic này (dữ liệu trong mô hình B) cần được hiển thị thông qua REST. Do đó, loại tính toán/logic này đi đâu?

Trả lời

11

Phần khung Django Rest là các khung nhìn (ViewSets, ApiViews, vv) và serializers. Không ai trong số đó là những nơi lý tưởng để viết logic. Như bạn đã đề cập, viết logic trong bất kỳ khung nhìn nào cũng không tốt. Tại sao?

  1. Không có cách nào để sử dụng cùng một logic từ một phần khác của ứng dụng
  2. Không có cách nào để đóng gói logic (bạn cần phải gọi quan điểm cho logic để chạy)
  3. Không có cách nào để kiểm tra đơn vị logic vì được ghép với chế độ xem

IMHO, các mô hình không phải là nơi tốt để viết logic. Hãy nghĩ về một mô hình làm định nghĩa cơ sở dữ liệu của bạn. Tôi sẽ giữ chúng càng đơn giản càng tốt. Bạn có thể ghi đè "lưu" và các phương pháp khác để thực hiện các tác vụ tầm thường. Bất kỳ chức năng nâng cao nào khác đều phải ở bên ngoài nó.

tôi có thể nghĩ đến hai nơi tốt hơn cho những gì bạn cần:

Một trong số đó là một django signal

Một một tốt hơn là một lớp tùy chỉnh. Encapsulate/tách logic trong lớp học riêng của bạn (bạn có thể sử dụng phương pháp tĩnh hoặc dụ, nó doesn't vấn đề), và sau đó bạn sẽ có thể:

  1. Đơn vị thi các phương pháp/nhạo báng lớp
  2. Tái sử dụng logic này ở một nơi khác
  3. đơn giản hóa mã của bạn theo KISS nguyên tắc
  4. Sử dụng nó từ một tín hiệu giữ mã tín hiệu đơn giản
  5. Sử dụng nó từ một nhiệm vụ cần tây (nếu bạn thực hiện điều này trong tương lai) mà không sửa đổi một một dòng của bạn mã

CẬP NHẬT Ví dụ về cách sắp xếp mã.

Từ nhận xét, rõ ràng là tín hiệu sẽ không hoạt động vì hoạt động phân tích sẽ chạy theo yêu cầu của người dùng. Một tín hiệu sẽ hữu ích nếu thao tác đó sẽ tự động chạy khi lưu một mô hình cụ thể.

Tôi giả sử bạn biết cách sử dụng chế độ xem khung cảnh django-rest-api hoặc lượt xem, serializers, v.v. Tôi không làm thế nào về điều đó, tốt hơn hãy hỏi một câu hỏi khác. Đây sẽ là giải thích về python nhiều hơn bất kỳ điều gì khác

Trong mô-đun ứng dụng của bạn, tạo một tệp app_business_logic.py hoặc bất kỳ điều gì bạn muốn gọi. Bạn có thể đặt nó ở cùng một mức độ các models.py ví dụ, nhưng đó là không bắt buộc:

class HoldingsAnalyser: 
    # static method sample. Call it like this: "HoldingsAnalyser.run(..)" 
    @staticmethod 
    def run(holding_list): 
     # do your model generation here or whatever you need 
     return True # or whatever you need to return 

    # instance method sample. Create an instance first and then call the method: 
    # analyser = HoldingsAnalyser() 
    # analyser.run(...) 
    def run(self, holding_list): 
     # do your model generation here or whatever you need 
     return True # or whatever you need to return 

Bây giờ, trong một cái nhìn api django-nghỉ ngơi-framework hoặc viewset, tạo ra một phương thức POST được gọi khi báo chí khách hàng sử dụng ứng dụng vào nút (nút đó để tạo ra phân tích):

from yourapp.app_business_logic import HoldingsAnalyser 

class StockPortfolioViewSet(WhatEverMixingYouNeedToInheritFrom): 
    serializer_class = whatever # look at the docs 

    @detail_route(methods=['post']) 
    def run_analysis(self, request, pk): 
     stock_portfolio = get the object based on the pk 
     holdings = make your query to get the holdings 
     analysis_result = HoldingsAnalyser.run(holdings) 
     if analysis_result: 
      # everything ok 
      return Response(status=status.HTTP_204_NO_CONTENT) 
     else: 
      return Response(a useful error for your client) 

url này sẽ là một cái gì đó giống như http://server.com/api_path/stockportfolio/21/run_analysis/, nơi 21 sẽ là id của StockPortfolio

+0

Cảm ơn @xleon cho Phản hồi. Tôi vẫn không chắc chắn về nơi mà tất cả điều này (tín hiệu hoặc các lớp tùy chỉnh) phù hợp với một dự án. Tôi đang hình dung người dùng sẽ xem xét phần lưu trữ của họ (Mẫu C) trong danh mục đầu tư của họ (Mẫu A). Sau đó, họ sẽ có thể chạy phân tích (lặp qua từng lần giữ và tạo các phiên bản Model B) bằng cách nhấp vào nút 'phân tích'. Cuối cùng, tất cả 3 mô hình sẽ có sẵn thông qua một API REST. Nếu người dùng không chạy phân tích thì API cho Mô hình B sẽ trống. Nếu logic phân tích nằm trong lớp tín hiệu hoặc lớp tùy chỉnh khi nào nó được gọi để điền vào API Mô hình B? – shudoh

+0

Nếu bạn chạy phân tích thông qua hành động của người dùng, tín hiệu django không phải là tùy chọn (chỉ được khuyến nghị nếu phân tích đó sẽ chạy tự động khi lưu mô hình khác). Tôi sẽ cập nhật câu trả lời với một số mã giả cho quy trình làm việc của bạn – xleon

+0

Chà. Ví dụ tuyệt vời. Tôi luôn tự hỏi về việc đặt logic nghiệp vụ trong models.py. Một số ấn phẩm phổ biến cho rằng đó là nơi để đặt nó, nhưng tôi đã luôn luôn có những nghi ngờ của tôi. –

Các vấn đề liên quan