假设我有一个模型椰子:
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
显然这不对,因为它与数据库中的现有数据相关联。
此外,如果尚未实例化“birds”应用程序,它会导致测试运行器出现问题。
那么正确的方法是什么?
我遇到这个问题时的一些例子:
答案 0 :(得分: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'
然后,您还依赖于配置应用程序中存在的数据,但现在这已经明确了。
答案 1 :(得分:0)
一个选项可以是使用模型信号(选择取决于何时/何地/如何需要默认值或被覆盖的值)和代理模型。
https://docs.djangoproject.com/en/dev/ref/signals/#module-django.db.models.signals
使用Django模型继承,您可以创建具有不同post / pre方法的代理模型,并共享同一个表。
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并不总是一个可用选项,如果没有灯具是您可能想要考虑的其他选项。
希望它有所帮助;)