首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Django Rest框架中,模型方法中的业务逻辑在哪里?

在Django Rest框架中,模型方法中的业务逻辑在哪里?
EN

Stack Overflow用户
提问于 2016-02-19 14:49:13
回答 1查看 4.6K关注 0票数 9

我有3种模式是相互关联的一对多的关系。

  • 模型A可以有许多B模型的实例。
  • 模型A可以有许多模型C的实例。
  • 模型B可以有许多模型C的实例。

其想法是用户将创建模型A的实例(如股票组合),然后输入股票持有量(Model C)。模型B适用的地方是,我希望根据投资组合中的股票(模型C)进行计算/逻辑(模式A),并使用另一个类/模型来跟踪事物,从而使生活变得更容易,因此模式B。

我最初在Django视图中有这些计算的逻辑,但是在Django的两个Scoops中看到业务逻辑应该从视图中分离出来。因此,我将逻辑转移到模型A( portfolio)的方法中,现在从视图中调用该方法。这个逻辑循环通过股票持有,并创建新的实例的模型B,结果。

我现在感兴趣的是探索django-rest框架,以便为javascript前端提供一个API (比如角)。我猜我将无法在REST接口中进行这种数据操作。但是,这个逻辑的结果(B模型中的数据)需要通过REST来显示。因此,这类计算/逻辑将走向何方?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-19 20:55:08

的主要部分是视图(ViewSets、ApiViews等)和序列化器。这两个地方都不是写逻辑的理想场所。正如您所提到的,在任何观点中编写逻辑都是不好的。为什么?

  1. 无法从应用程序的另一部分使用相同的逻辑
  2. 无法封装逻辑(需要调用视图才能运行逻辑)
  3. 无法对逻辑进行单元测试,因为它与视图耦合。

IMHO,模型不是写逻辑的好地方。将模型视为数据库定义。我会尽量保持简单。您可以重写“保存”和其他方法来执行琐碎的任务。任何其他高级功能都应该存在于它之外。

我可以想出两个更好的地方来满足你的需要:

其中一个是django信号

更好的方法是定制类。将逻辑封装/解耦到您自己的类中(您可以使用静态或实例方法,这无关紧要),然后您将能够:

  1. 单元测试那些方法/模拟那个类
  2. 在其他地方重用这个逻辑
  3. 根据接吻原则简化代码
  4. 使用它从一个信号保持简单的信号代码
  5. 在不修改一行代码的情况下,从芹菜任务中使用它(如果将来实现此任务)

UPDATE如何组织代码的示例。

从评论中可以清楚地看到,信号无法工作,因为分析操作将根据用户请求运行。如果该操作在保存特定模型时自动运行,则信号将非常有用。 我假设您知道如何使用django-rest框架api视图或视图集、序列化器等。这将更多的是蟒蛇的解释,而不是任何其他的解释。

在你的应用模块中,创建一个文件app_business_logic.py或任何你想叫它的东西。例如,您可以将它放在models.py的同一级别,但这不是强制性的:

代码语言:javascript
复制
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

现在,在django-rest框架api视图或视图集中,创建一个POST方法,以便在客户端应用程序用户按下按钮(该按钮用于生成分析)时调用:

代码语言:javascript
复制
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类似于http://server.com/api_path/stockportfolio/21/run_analysis/,其中21将是StockPortfolio的id。

票数 20
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35508064

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档