2014-10-04 117 views
1

我有一个帐户模型的工作,我想内部连接,而不必在帐户中创建模型的附加settings_id列,因为该帐户的PK表格完全匹配设置表格上的PK。我一直试图建立这些表&列之间的OneToOne关系,但无法弄清楚如何做到这一点,而无需创建一个新的列或东西。我试图尽可能地使用现有的模式,并且宁愿不创建不必要的列。的Django模型OneToOneField,而无需创建额外的_id数据库列

Class Account(models.Model): 
    login_id = models.AutoField(primary_key=True) 
    settings = models.OneToOneField('Settings', to_field='login_id', null=True, 
     related_name='settings', db_column='login_id') # Doesn't work because login_id already exists.... 


Class Settings(model.Model): 
    login_id = models.OneToOneField('Account', to_field='login_id', related_name='account') 

基本上,我试图复制该查询:

SELECT * FROM account 
INNER JOIN settings 
ON account.login_id=settings.login_id 
WHERE account.login_id=1 

基于错误,Django的ORM似乎对创建的账户表中的新列真执着,但我不”当两个表格之间的关系如此简单时,请参阅添加新列的要点:account.login_id = settings.login_id

+0

为什么你有指向对方两个模型一比一的关系?你不需要在双方指定。在其中任何一个上移除它。正向和反向关系通过ORM可达 – karthikr 2014-10-04 02:25:44

+0

由于它们是相关的,它似乎是合乎逻辑的。我不认为这是我创建的错误,但我会尝试从“设置”模型中删除关系,看看是否有帮助。 – 2014-10-04 02:26:56

+0

这将是问题的一部分。另一件事是 - 你究竟想达到什么目的?看起来你不需要在典型情况下运行这样的查询。 – karthikr 2014-10-04 02:30:36

回答

4

尽管我自己从未尝试过,但声明OneToOneField应为主键。

class Account(models.Model): 
    login_id = models.AutoField(primary_key=True) 

class Settings(model.Model): 
    account = models.OneToOneField('Account', to_field='login_id', 
     primary_key=True, related_name='settings') 

声明的primary_key将继续从Django的努力为您创建一个主键列,并用此设置,您可以访问account.settingssettings.accountsettings.account_id

+0

谢谢,这是答案。我没有完全理解'related_name'是如何工作的。通过我正在使用的模式,我不需要使用您提出的'primary_key = True'建议。 – 2014-10-06 16:41:08

+0

对于我来说,你可以基本上从另一个模型的属性中的一个参数定义一个模型的属性,这很奇怪。看起来这会让一个非常庞大的代码库带来很多模型关系,这些代码关系有点令人困惑。 – 2014-10-06 16:46:38

+0

@CoryDanielson:这里有一种固有的紧张感,就是*显式*和*不重复自己*。 Django始终更喜欢DRY,而比方说,SQLAlchemy定义了关系两端的字段(我认为)。 Django的方法对我来说很合适。另一方面,在一个'ManyToManyField'的情况下,在后台创建一个新的表格,我几乎总是喜欢明确地设置该表格。 – 2014-10-06 17:35:26

1

这里是我落得这样做:

class Account(models.Model): 
    login_id = models.AutoField(primary_key=True) 

    def get_settings_dict(self): 
     try: 
      return self.settings.to_dict() 
     except Settings.DoesNotExist: 
      return Settings.get_defaults_dict() 

class Settings(model.Model): 
    account = models.OneToOneField('Account', to_field='login_id', related_name='settings') 
    # other settings properties 
    # other settings properties 

    def to_dict(self): 
     # return current values as dict 

    @staticmethod 
    def get_defaults_dict(): 
     # return default values dict 

这让我通过account.settings访问用户的设置,而无需创建帐户模型的附加settings_id列。 OneToOne关系在两个模型上都不需要。

此外,get_settings_dict方法返回默认设置时为用户还不存在的设置。这是一个很好的方便,可以防止我每次通过account.settings访问用户设置时都必须执行空检查。

相关问题