【问题标题】:should I define another class for a django model我应该为 django 模型定义另一个类吗
【发布时间】:2016-04-23 03:54:39
【问题描述】:

django 模型实例与数据库有关系,而当我将对象从 ModelName.objects.get() 传递到上层时。我不想暴露它可以访问数据库的操作,例如:save()、delete()。因此,我目前定义了另一个类(比如 Product),其中的属性与 Model 类(比如 ProductModel)中的属性几乎相同。 每次我需要实例时,我都会从另一个复制属性。应该有更好的做法,不是吗?

from django.db import models
class ProductModel(models.Model):
    price = models.FloatField(default=0.0)

class Product(object):
    def __init__(self):
        self.id = 1
        self.price = 12.3

【问题讨论】:

  • 如果您不将其保存在引用模型(或管理员)的视图中,则无法访问该模型。用户不能直接访问模型实例,只能向视图提交数据。
  • 谢谢。恐怕我没有很好地表达我的问题。如果我在一个函数中返回模型实例,而在另一个调用该函数的模块中,则实例方法是可调用的。
  • 是的,通过您的代码。你到底想保护自己免受什么伤害?
  • @DanielRoseman 也许我需要一个模型实例的副本,它不再影响原始实例,但正如 Robert Moskal 的帖子所说,这将“失去强大的功能,如通过延迟加载关系和查询的能力查询集”。

标签: python django orm


【解决方案1】:

您正在描述 DTO(数据传输对象)模式,可能是为了防止客户端代码直接调用模型上的 CRUD 方法。

我认为这种模式在 django 中是单一的。首先,如果不将模型直接传递给视图和模板上下文,您将失去强大的功能,例如通过 QuerySet 延迟加载关系和查询的能力。

如果你想在你的 crud 操作上执行某些业务逻辑,还有更多类似 django 的解决方案。信号是一个:https://docs.djangoproject.com/en/1.9/ref/signals/ 您可以使用它们来创建保存前和保存后挂钩。客户端代码可以很高兴地不知道它们的操作。

一旦您开始在模型中拥有大量业务逻辑,建议引入服务对象。客户端代码应在需要时通过服务对象进行交互。除了约定、协议、代码审查,也许还有分析工具之外,没有硬性的方法可以确保这一点。

话虽如此,没有什么能阻止您编写一个简单的映射器,将 django 模型转换为服务层中的普通旧 python 对象。您只需要遍历模型上的数据库字段并在 python 对象或字典上设置属性,然后在更新操作上反转该过程。这让我觉得太过仪式(而且我可能选择了一种不像 django 那样围绕 ActiveRecord 模式旋转的技术)。

【讨论】:

    猜你喜欢
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2021-06-18
    • 1970-01-01
    • 2014-07-30
    • 2014-07-25
    相关资源
    最近更新 更多