访问时自动创建OneToOneField

时间:2013-03-20 03:52:53

标签: python django one-to-one relation

我有两种模式:

class Profile(models.Model):
    # (...)
    settings = models.OneToOneField('Settings', null=True)
    # (...)

class Settings(model.Model):
    # (...)

是否有办法在访问个人资料#设置时创建设置的实例?

更新:我想要这样做的主要动机是我已经拥有个人资料模型,我希望设置关系可以懒惰地创建当用户点击需要个人资料#设置实例的应用点时,无需关心是否已创建。

更新: @ miki725下面说这是由Django处理的。我尝试了以下方法:

class SettingsTest(TestCase):
    def setUp(self):
        user = User.objects.create(username='felipe', email='something@aol.com')
        self.profile = Profile.objects.create(short_name='Felipe', name='Felipe',
            user=user)

    def test_settings(self):
        self.assertIsNotNone(self.profile.settings)

我明白了:

Creating test database for alias 'default'...
F
======================================================================
FAIL: test_settings (activity.tests.settings.SettingsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/vagrant/activity/tests/settings.py", line 20, in test_settings
    self.assertIsNotNone(self.profile.settings)
AssertionError: unexpectedly None

----------------------------------------------------------------------
Ran 1 test in 0.003s

1 个答案:

答案 0 :(得分:1)

由Django自动完成!

>>> p = Profile.objects.get(...)
>>> isinstance(p.settings, Settings)
True

<强>更新

如果您收到None,则表示Profile模型中的外键值为null,因为您允许空值null=True。在这种情况下,你无法做任何事情:

>>> p = Profile(settings=None, ...)
>>> p.save()
>>> p = Profile.objects.get(pk=p.pk)
>>> p.settings # the settings can't be anything because you never assigned them
None

如果您需要进行测试,那么您必须为Profile实例分配一些设置值:

class SettingsTest(TestCase):
    def setUp(self):
        user = User.objects.create(username='felipe', email='something@aol.com')
        self.settings = Settings.objects.create(...)
        self.profile = Profile.objects.create(short_name='Felipe',
                                              name='Felipe',
                                              user=user,
                                              settings=self.settings)

顺便说一句,从Django 1.5开始,您可以配置您的用户模型。在必须创建必须具有用户模型的一对一密钥的配置文件模型之前。现在已经不再需要了。您只需将字段添加到用户模型即可。您可以在Django 1.5发行文档(https://docs.djangoproject.com/en/dev/releases/1.5/#configurable-user-model)中阅读更多相关信息。

<强>更新

现在您的动机更加明确,您可以使用这种hackish方法实现这一目标。我不认为这是最好的方法,但它应该有效:

Profile(models.Model):
    def get_default_settings(self):
        settings = Settings.objects.create(...)
        self.settings_id = settings.pk
        return settings

    def __getattribute__(self, name):
        default = object.__getattribute__(self, name)
        if name == 'settings':
            if default is None:
                return self.get_default_settings()
            else:
                return default
        else:
            return default