使用 OneToOne 字段保存 Django 模型时出错 - 列指定了两次
Error saving django model with OneToOne field - Column specified twice
这个问题以前有人问过,但是那里的答案没有解决我的问题。
我使用的是遗留数据库,无法更改任何内容
这是我的 Django 模型,除了相关字段之外的所有字段都被删除,显然 class meta 在我的实际代码中有 Managed=False:
class AppCosts(models.Model):
id = models.CharField(primary_key=True)
cost = models.DecimalField()
class AppDefs(models.Model):
id = models.CharField(primary_key=True)
data = models.TextField()
appcost = models.OneToOneField(AppCosts, db_column='id')
class JobHistory(models.Model):
job_name = models.CharField(primary_key=True)
job_application = models.CharField()
appcost = models.OneToOneField(AppCosts, to_field='id', db_column='job_application')
app = models.OneToOneField(AppDefs, to_field='id', db_column='job_application')
OneToOne 字段非常适合查询,我使用 select_related()
得到了正确的结果
但是当我为 JobHistory 表创建新记录时,当我调用 save() 时,我得到:
DatabaseError: (1110, "Column 'job_application' specified twice")
我使用的是 django 1.4,我不太明白这个 OneToOneField 是如何工作的。我找不到任何主键命名不同且具有这种特定语义的示例
我需要可以执行此 SQL 的 django 模型:
select job_history.job_name, job_history.job_application, app_costs.cost from job_history, app_costs where job_history.job_application = app_costs.id;
您已将 appcost 和 app 定义为具有相同的基础数据库列,job_application
,也是另一个现有字段的名称:因此三个字段共享同一列。这根本没有意义。
OneToOneFields 只是在两端都被限制为单个值的外键。如果您有从 JobHistory 到 AppCost 和 AppDef 的外键,那么大概您的数据库中有包含这些外键的实际列。这些是您应该为这些字段使用 db_field
的值,而不是 "job_application".
编辑很高兴你说你没有设计这个模式,因为它非常可怕:你不会有任何外键约束,例如,使参照完整性成为不可能。不过没关系,我们实际上或多或少可以达到你想要的。
你有各种各样的问题,但最主要的是你根本不需要单独的 "job_application" 字段。也就是说,正如我之前所说的,外键,就这样吧。还要注意它应该是一个实际的外键字段,而不是一对一的,因为一个应用程序有很多历史记录。
我们在 Django 中无法轻松实现的一个约束是让相同的字段充当两个表的 FK。但这并不重要,因为我们可以通过 AppDefs 获取 AppCosts。
所以模型可以看起来像这样:
class AppCosts(models.Model):
app = models.OneToOneField('AppDefs', primary_key=True, db_field='id')
cost = models.DecimalField()
class AppDefs(models.Model):
id = models.CharField(primary_key=True)
data = models.TextField()
class JobHistory(models.Model):
job_name = models.CharField(primary_key=True)
app = models.ForeignKey(AppDefs, db_column='job_application')
请注意,我已将 Costs 和 Defs 之间的一对一转移到 AppCosts 上,因为在 Defs 中拥有规范 ID 似乎很有意义。
现在,给定一个 JobHistory 实例,您可以 history.app
获取应用实例,history.app.cost
获取应用成本,并使用 history.app_id
获取底层应用job_application 列中的 ID。
如果您想更准确地重现 SQL 输出,现在可以使用类似这样的方法:
JobHistory.objects.values_list('job_name', 'app_id', 'app__appcosts__cost')
这个问题以前有人问过,但是那里的答案没有解决我的问题。
我使用的是遗留数据库,无法更改任何内容
这是我的 Django 模型,除了相关字段之外的所有字段都被删除,显然 class meta 在我的实际代码中有 Managed=False:
class AppCosts(models.Model):
id = models.CharField(primary_key=True)
cost = models.DecimalField()
class AppDefs(models.Model):
id = models.CharField(primary_key=True)
data = models.TextField()
appcost = models.OneToOneField(AppCosts, db_column='id')
class JobHistory(models.Model):
job_name = models.CharField(primary_key=True)
job_application = models.CharField()
appcost = models.OneToOneField(AppCosts, to_field='id', db_column='job_application')
app = models.OneToOneField(AppDefs, to_field='id', db_column='job_application')
OneToOne 字段非常适合查询,我使用 select_related()
得到了正确的结果但是当我为 JobHistory 表创建新记录时,当我调用 save() 时,我得到:
DatabaseError: (1110, "Column 'job_application' specified twice")
我使用的是 django 1.4,我不太明白这个 OneToOneField 是如何工作的。我找不到任何主键命名不同且具有这种特定语义的示例
我需要可以执行此 SQL 的 django 模型:
select job_history.job_name, job_history.job_application, app_costs.cost from job_history, app_costs where job_history.job_application = app_costs.id;
您已将 appcost 和 app 定义为具有相同的基础数据库列,job_application
,也是另一个现有字段的名称:因此三个字段共享同一列。这根本没有意义。
OneToOneFields 只是在两端都被限制为单个值的外键。如果您有从 JobHistory 到 AppCost 和 AppDef 的外键,那么大概您的数据库中有包含这些外键的实际列。这些是您应该为这些字段使用 db_field
的值,而不是 "job_application".
编辑很高兴你说你没有设计这个模式,因为它非常可怕:你不会有任何外键约束,例如,使参照完整性成为不可能。不过没关系,我们实际上或多或少可以达到你想要的。
你有各种各样的问题,但最主要的是你根本不需要单独的 "job_application" 字段。也就是说,正如我之前所说的,外键,就这样吧。还要注意它应该是一个实际的外键字段,而不是一对一的,因为一个应用程序有很多历史记录。
我们在 Django 中无法轻松实现的一个约束是让相同的字段充当两个表的 FK。但这并不重要,因为我们可以通过 AppDefs 获取 AppCosts。
所以模型可以看起来像这样:
class AppCosts(models.Model):
app = models.OneToOneField('AppDefs', primary_key=True, db_field='id')
cost = models.DecimalField()
class AppDefs(models.Model):
id = models.CharField(primary_key=True)
data = models.TextField()
class JobHistory(models.Model):
job_name = models.CharField(primary_key=True)
app = models.ForeignKey(AppDefs, db_column='job_application')
请注意,我已将 Costs 和 Defs 之间的一对一转移到 AppCosts 上,因为在 Defs 中拥有规范 ID 似乎很有意义。
现在,给定一个 JobHistory 实例,您可以 history.app
获取应用实例,history.app.cost
获取应用成本,并使用 history.app_id
获取底层应用job_application 列中的 ID。
如果您想更准确地重现 SQL 输出,现在可以使用类似这样的方法:
JobHistory.objects.values_list('job_name', 'app_id', 'app__appcosts__cost')