1

我有一个具有以下模型的现有应用程序

class Contact(models.Model):
     lastname = models.CharField(max_length=200)
     firstname = models.CharField(max_length=200)
     ...

class Journalist(Contact):
     pass

我的数据库中有一个Contact,我希望它变成一个Journalist.

在原始 sql 中,它看起来像insert into app_journalist values (25624);. 在此示例中,25624 是现有联系人的 ID。它似乎工作正常,django 应用程序似乎很开心。

但是,我想用 django ORM 做同样的事情。我尝试了几种方法,例如强制记者 id ( Journalist(id=25624)),但它会创建一个新联系人,而不是链接到现有联系人。

使用 Django ORM 可以做到这一点吗?如何?

在此先感谢您的帮助

4

3 回答 3

3

解决此问题的一种方法是(不更改模型结构)将实例的contact_ptr属性设置Journalist为适当的Contact实例。例如

contact = Contact.objects.get(pk = 25624)
journalist = Journalist(contact_ptr = contact)
journalist.save()

如果您首先查看表格,这将变得更容易理解app_journalist。它只有一列,contact_ptr_id. 因此,当您执行时,insert into app_journalist values (25624)您是contact_ptr_id = 25624在 SQL 级别进行设置。相应地,您应该 contact_ptr = <instance of Contact>在 ORM 级别设置 。

更新

还有其他方法可以解决问题,但它们需要更改现有模型。正如@bugspy.net指出的那样,您可以使用通用关系。或者,您可以声明一个附加type字段来指定联系人是否是记者、同事等。

更新 2

还可以看看这个演示片段(和完整的代码),它允许您使用多态继承(SQLAlchemy 已经这样做了)。

更新 3

正如@luc 自己指出的那样(见下面的评论)

journalist = Journalist(contact_ptr = contact)

单独是不够的。这将覆盖to的firstnameand 。为避免这种情况,您必须将每个字段显式分配给.lastnamecontact""Journalist

于 2010-10-06T09:31:51.913 回答
2

Django 的Contenttypes框架非常方便。您可以使用它来表示不同的联系人类型:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Contact(models.Model):
     lastname = models.CharField(max_length=200)
     firstname = models.CharField(max_length=200)
     content_object = generic.GenericForeignKey('content_type', 'object_id')
于 2010-10-06T09:55:35.060 回答
0

模型级别的继承通常不是一个好主意。大多数 ORM 让你这样做。大多数 ORM 甚至为能够做到这一点而感到自豪。在模型层面,著名的“更喜欢组合而不是继承”比以往任何时候都更加真实。

在您的情况下,您可以说:“一个人有一份工作,在这种情况下是记者” ,而不是说: “记者是一个人” 。这将由一个由 Job 类组成的 Person 类来表示。其中一项工作可能是“记者”。

组合方法可以让你让一个人换工作,甚至有多个工作。

当然,这并不能直接回答你的问题,但是其他的答案已经很不错了!

于 2010-10-06T11:10:37.277 回答