【问题标题】:Django: Question about model architectureDjango:关于模型架构的问题
【发布时间】:2010-01-06 22:34:42
【问题描述】:

这个外观代码看起来是个好主意,还是设计本身存在缺陷?更重要的是,我可能会在这段代码中遇到问题吗?非常感谢任何帮助。

我正在尝试构建它,以便我可以有一个 Payment 类作为我的门面,它接受 cc 号码等,以及一个 PayPal 类作为我的实现,以便我可以从卡上收费并存储相关信息,等等

class MyFacadeClass(models.Model):
    account = models.ForeignKey('Account')  # Account omitted from example for brevity.
    implementation = CharField(max_length=255, choices=IMPL_CHOICES)  # IMPL_CHOICES omitted for brevity
    some_field = models.CharField(max_length=255)

    def __init__(self, *args, **kwargs):
        super(MyFacadeClass, self).__init__(*args, **kwargs)
        if self.implementation == 'PAYPAL':
            from somewhere import MyPayPalImplementationModelClass
            self.impl = MyPayPalImplementationModelClass(my_facade_instance=self, some_field=self.some_field, account=self.account)
            # Then MyPayPalImplementationModelClass does stuff with PayPal and has its own attributes such as ack, and datetime and fee_amount behind the scenes.

    def save(self, force_insert=False, force_update=False)
        if self.impl.is_valid():
            self.impl.save()
        super(MyFacadeClass, self).save(force_insert, force_update)

【问题讨论】:

    标签: django django-models django-project-architect


    【解决方案1】:

    仅通过查看上面的代码,并不清楚您的“实现”类的目标是什么。目前尚不清楚实现类是另一个 ORM 模型,还是只是提供 save() 方法的自定义类。

    略读以上内容的几个陷阱。

    行:

    self.impl = MyImplementationClass(my_facade_class_instance=self, some_field=self.some_field, account=self.account)
    

    出现在对 super() 的调用之前,这意味着 self.some_fieldself.account 在您将其传递给其他模型时很可能没有正确初始化。

    第二个问题在于,如上所述,两个实例将(可能取决于 MyImplementationClass 的编写方式)包含对彼此的循环引用。这意味着当对象超出范围时引用计数不会为 0。循环 GC(可能)最终会垃圾收集这些对象,但您会失去确定性垃圾收集,这(在我看来)是 Python 的一个非常强大的特性。


    看来您正在尝试实现所谓的“通用关系”,这是 django 的 contrib.contenttypes 应用程序已经提供的功能:http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1 如果您只想要一个可以引用多种模型类型之一的对象,您可以使用“contenttypes”中的通用关系来实现。

    【讨论】:

    • 您能否澄清一下对象引用计数不会变为 0,以及这将如何导致循环 GC 无法尽快完成它的工作。这是否意味着如果我在外观的 self.impl 中引用了实现模型,那么在我使用完外观后,实现模型的 mem 将不会是 GC?
    • MyImplemenationClass 是一个 ORM 模型。
    • 这取决于 MyPaypalImplementation 对其第一个参数 my_facade_instance 参数的作用。如果您在MyPaypalImplementation.__init__ 中执行类似self.my_facade = my_facade_instance 的操作,那么当两个对象超出范围时(不进行手动循环中断).my_facade 将指向您的外观实例,并且外观的.impl 属性将指向回到执行。然后两者的引用计数都为 1。这个循环最终会被 gc 打破,但我不喜欢“最终”。
    • 这正是我要做的,所以我可以创建一个到外观类的链接为payment=OneToOneField(Payment)(我真正的外观类是Payment),然后设置self.payment =my_facade_instance
    • 在这种情况下你会做些什么不同的事情。我唯一能想到的就是创建一个名为 paypal_implementation=ForeignKey(PayPal, null=True) 的字段,然后将值设置为我在 Facade.__init__() 中创建的实例。不过,这对我来说似乎有点倒退,因为稍后我必须创建 two_checkout_implementation=ForeignKey(TwoCheckout, null=True)
    猜你喜欢
    • 2020-10-08
    • 2011-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-13
    • 2011-05-10
    相关资源
    最近更新 更多