2010-01-06 73 views
1

这个外观代码看起来是个好主意,还是设计中存在固有的缺陷?更重要的是,有没有一个问题,我可能会遇到这个代码在道路上?任何帮助深表感谢。Django:关于模型架构的问题

我试图建立这个,这样我可以有一个支付类作为我的门面,它接受cc数字等,并将贝宝类作为我的实现,以便我可以为该卡充电并存储有关该信息的信息等等。

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) 

回答

2

只是通过查看上面的代码,您的“实现”类旨在实现的目标并不完全清楚。目前还不清楚实现类是否是另一个ORM模型,或者只是一个提供save()方法的自定义类。

只是略读了上面的几个问题。

行:

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

来调用超(),这意味着它极有可能self.some_fieldself.account不正确你将它传递给其他模型的时候初始化之前。

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


您似乎在试图实现了所谓的“通用的关系”,这是已被Django的contrib.contenttypes应用程序提供的功能:http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#id1如果你只是想要一个对象,它可以指很多之一模型类型,你可以通过使用“contenttypes”的通用关系来实现。

+0

您能否澄清一下对象引用计数不会变为0,以及这将如何导致循环GC不能及时完成工作。这是否意味着如果我在Facade的self.impl中引用了实现模型,那么在完成使用外观之后,实现模型的mem将不会是GC? – orokusaki 2010-01-06 23:08:50

+0

MyImplemenationClass是一个ORM模型。 – orokusaki 2010-01-06 23:43:31

+0

这取决于MyPaypalImplementation对第一个参数my_facade_instance的作用。如果你在'MyPaypalImplementation .__ init__'内执行'self.my_facade = my_facade_instance',那么当两个对象超出范围时(没有执行手动循环中断),'.my_facade'将指向你的外观实例,门面的'.impl'属性将指向实现。 两者的引用计数都是1.这个循环最终会被gc打破,但我并不是“最终”的粉丝。 – Crast 2010-01-07 00:53:49