简体   繁体   English

使用OneToOne字段保存Django模型时出错-列指定了两次

[英]Error saving django model with OneToOne field - Column specified twice

This question has been asked before, but the answers there do not solve my problem. 之前已经问过这个问题,但是那里的答案并不能解决我的问题。

I am using a legacy database, nothing can be changed 我正在使用旧版数据库,无法更改

Here are my django models, with all but the relevant fields stripped off, obviously class meta has Managed=False in my actual code: 这是我的django模型,除了相关字段以外的所有内容都被删除,很明显,类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')

The OneToOne fields work fine for querying, and I get the correct result using select_related() OneToOne字段适合查询,我可以使用select_related()获得正确的结果

But when I create a new record for the JobHistory table, when I call save(), I get: 但是,当我为JobHistory表创建新记录时,当我调用save()时,我得到:

DatabaseError: (1110, "Column 'job_application' specified twice")

I am using django 1.4 and I do not quite get how this OneToOneField works. 我正在使用django 1.4,但我不太了解这个OneToOneField的工作方式。 I can't find any example where primary keys are named differently and has this particular semantics 我找不到任何示例,其中主键的名称不同并且具有这种特殊的语义

I need the django model that would let me do this SQL: 我需要让我执行以下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;

You have defined appcost and app to have the same underlying database column, job_application , which is also the name of another existing field: so three fields share the same column. 您已将appcost和app定义为具有相同的基础数据库列job_application ,这也是另一个现有字段的名称:因此,三个字段共享同一列。 That makes no sense at all. 那根本没有道理。

OneToOneFields are just foreign keys constrained to a single value on both ends. OneToOneFields只是两端都限制为单个值的外键。 If you have foreign keys from JobHistory to AppCost and AppDef, then presumably you have actual columns in your database that contain those foreign keys. 如果您有从JobHistory到AppCost和AppDef的外键,则大概数据库中有包含这些外键的实际列。 Those are the values you should be using for db_field for those fields, not "job_application". 这些是您应该为这些字段而不是“ job_application”用于db_field的值。

Edit I'm glad you said you didn't design this schema, because it is pretty horrible: you won't have any foreign key constraints, for example, which makes referential integrity impossible. 编辑我很高兴您说您没有设计此架构,因为它非常可怕:例如,您将没有任何外键约束,这使得引用完整性成为不可能。 But never mind, we can actually achieve what you want, more or less. 但没关系,我们实际上可以或多或少地实现您想要的。

There are various issues with that you have, but the main one is that you don't need the separate "job_application" field at all. 您可能遇到各种各样的问题,但主要的问题是根本不需要单独的“ job_application”字段。 That is, as I said earlier, the foreign key, so let it be that. 正如我前面所说的,外键就是这样。 Also note it should be an actual foreign key field, not a one-to-one, since there are many histories to one app. 还要注意,这应该是实际的外键字段,而不是一对一,因为一个应用程序有很多历史记录。

One constraint that we can't achieve easily in Django is to have the same field acting as FK for two tables. 在Django中我们不容易实现的一个约束是要让两个表具有相同的字段作为FK。 But that doesn't really matter, since we can get to AppCosts via AppDefs. 但这并不重要,因为我们可以通过AppDefs到达AppCosts。

So the models could just look like this: 因此,这些模型可能看起来像这样:

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')

Note that I've moved the one-to-one between Costs and Defs onto AppCosts, since it seems to make sense to have the canonical ID in Defs. 请注意,我已经在Costs和Defs之间一对一地移动到AppCosts上,因为在Defs中具有规范的ID似乎很有意义。

Now, given a JobHistory instance, you can do history.app to get the app instance, history.app.cost to get the app cost, and use the history.app_id to get the underlying app ID from the job_application column. 现在,在给定JobHistory实例的情况下,您可以执行history.app获取应用程序实例, history.app.cost获取应用程序成本,并使用history.app_id从job_application列获取基础应用程序ID。

If you wanted to reproduce that SQL output more exactly, something like this would now work: 如果您想更精确地重现该SQL输出,则现在可以执行以下操作:

JobHistory.objects.values_list('job_name', 'app_id', 'app__appcosts__cost')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM