2011-10-10 94 views
1

比方说,我有一个模型椰子:Django的:另一个模型的方法使用一个模型实例

class Coconut(models.Model): 
    carrier = models.ForeignKey('birds.Swallow') 
    husk_color = models.IntegerField(Choices=COLORS) 
在某些情况下,我想设置视图承运人或管理命令或其它地方

现在。

然而,在其他情况下,我想默认是一个特定的燕子。

我很想:

BERT_THE_AFRICAN_SWALLOW = Swallow.objects.get(id=7) 
    def set_carrier(swallow=BERT_THE_AFRICAN_SWALLOW): 
     self.carrier = swallow 

显然,这是不对的,因为它连接到数据库中现有的数据。

此外,如果“鸟”应用程序尚未实例化,它会导致测试运行者博克。

那么正确的方法是什么?

的时间的一些例子,当我遇到这样的问题:

  • 分配自动化过程的“创造者”用户,这实际上是各种各样的机器人
  • 在VOIP应用,分配特定的过程,以特定的预定义PhoneNumber对象
  • 在自定义授权方案中,组合预定义的权限或权限对象。

回答

1

我的理解是,你真正想要做的是配置某种默认对象。您可以为此创建一个配置应用程序,以便您可以在管理界面中进行配置,或将其存储在固定装置中或其他东西中。

将字符串(配置选项)映射到任何类型的对象的模型都可以。 contenttype应用程序非常适合您需要的那种外键。

# models.py 

from django.db import models 
from django.db.contenttypes.models import ContentType 
from django.db.contenttypes import generic 

class ConfigurationOption(models.Model): 

    name = models.SlugField(max_length = 255, unique=True) 

    value_id = models.PositiveIntegerField() 
    value_type = models.ForeignKey(ContentType) 
    value = generic.GenericForeignKey('value_type', 'value_id') 

    class Meta: 
     unique_together = 'value_id', 'value_type' 

然后您还依赖于数据在配置应用程序存在,但现在是作出了明确。

+0

这非常有趣。我可以研究这项技术的历史吗? – jMyles

+0

当然有。身份验证应用程序使用contenttypes来设置权限。 – pvoosten

0

一个选项可以使用模型信号(选择取决于何时/何地/如何需要值在那里默认或重载)和代理模型。

https://docs.djangoproject.com/en/dev/ref/signals/#module-django.db.models.signals

使用Django模型继承您可以创建具有不同岗位/预方法代理模式,共享同一个表。

https://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models

class Coconut(models.Model): 
    carrier = models.ForeignKey('birds.Swallow') 
    husk_color = models.IntegerField(Choices=COLORS) 

class CoconutCarriedByShallow(Coconut): 
    pass 

    class Meta(): 
     proxy = True 

cached_carriers_dict = {} 

def assign_shallow_carrier(sender, instance, **kwargs): 
    import birds.models 
    attrs = {'name': 'Jhon', 'kind': 'super-fast'} 
    carrier = cached_carriers_dict.get(tuple(attrs.items())) 
    if carrier is None: 
     defaults = {'color': 'blue'} 
     carrier, c = birds.models.Swallow.objects.get_or_create(**attrs, defaults= defaults) 
     cached_carriers_dict.update({tuple(attrs.items()): carrier}) 
    instance.carrier = carrier 

models.signals.post_init.connect(assign_shallow_carrier, sender=CoconutCarriedByShallow) 

当然get_or_create并不总是可用的选项,如果没有灯具,你可能要考虑的另一种选择。

希望它帮助;)

+0

虽然这是有趣的和内容丰富的,但我没有看到它解决了我的问题中描述的需求。我如何使用这个来推广我所描述的模型实例? – jMyles

+0

@jMyles我已经扩展了这个例子 –

+0

我明白你现在要去哪里。我不喜欢这个,原因很多,其中最重要的就是get_or_create所带来的性能提升。另外,我不能用pre_save做同样的事情并修改kwargs吗? 这两个问题很小;这是最大的一个:我仍然需要进口鸟类。因此,该testrunner仍然会抱怨。 – jMyles

相关问题