我想在django模型中设置一个ForeignKey
字段,该字段在某些时候指向另一个表。但是我希望可以在这个字段中插入一个id,这个字段引用另一个表中可能不存在的条目。因此,如果该行存在于另一个表中,我希望获得ForeignKey关系的所有好处。但如果没有,我希望这只被视为一个数字。
这可能吗?这是通用关系的用途吗?
答案 0 :(得分:7)
很久以前就问过这个问题,但是对于新手来说,现在有一种内置的方法可以通过在ForeignKey上设置db_constraint = False来处理这个问题:
https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.ForeignKey.db_constraint
customer = models.ForeignKey('Customer', db_constraint=False)
或者如果您想要可以为空并且不强制引用完整性:
customer = models.ForeignKey('Customer', null=True, blank=True, db_constraint=False)
我们在不能保证以正确的顺序创建关系的情况下使用它。
编辑:更新链接
答案 1 :(得分:3)
我是Django的新手,所以我现在不提供你想要的开箱即用的东西。我想到了这样的事情:
from django.db import models
class YourModel(models.Model):
my_fk = models.PositiveIntegerField()
def set_fk_obj(self, obj):
my_fk = obj.id
def get_fk_obj(self):
if my_fk == None:
return None
try:
obj = YourFkModel.objects.get(pk = self.my_fk)
return obj
except YourFkModel.DoesNotExist:
return None
我不知道您是否使用contrib admin应用程序。使用PositiveIntegerField而不是ForeignKey,将在管理站点上使用文本字段呈现该字段。
答案 2 :(得分:3)
这可能就像声明ForeignKey并创建列而不实际声明为FOREIGN KEY一样简单。这样,你将获得o.obj_id,如果对象存在,o.obj将起作用,并且 - 我认为 - 如果你试图加载一个实际上不存在的对象,可能会引发异常(可能是{{1} })。
但是,我认为没有办法让DoesNotExist
为你做这件事。我发现syncdb
限制为无用,所以我完全绕过它并使用我自己的代码创建模式。您可以使用syncdb创建数据库,然后直接更改表,例如。 syncdb
。
当然,您还会失去ON DELETE CASCADE和所有参照完整性检查。
答案 3 :(得分:3)
要通过南方的@Glenn Maynard做出解决方案,请生成一个空的南迁移:
python manage.py schemamigration myapp name_of_migration --empty
编辑迁移文件,然后运行它:
def forwards(self, orm):
db.delete_foreign_key('table_name', 'field_name')
def backwards(self, orm):
sql = db.foreign_key_sql('table_name', 'field_name', 'foreign_table_name', 'foreign_field_name')
db.execute(sql)
答案 4 :(得分:1)
(注意:如果您解释为什么要这样做,可能会有所帮助。可能有更好的方法来解决潜在的问题。)
这可能吗?
不单独使用ForeignKey,因为您使用两种不同的含义重载列值,而没有可靠的方法来区分它们。 (例如,如果使用与引用表中的旧条目匹配的主键创建目标表中的新条目会发生什么情况?删除新目标条目时这些旧引用条目会发生什么?)
此问题的通常临时解决方案是在外键旁边定义“类型”或“标记”列,以区分不同的含义(但请参见下文)。
这是通用关系的用途吗?
是的,部分原因。
GenericForeignKey只是上面模式的Django便利助手;它将外键与类型标记配对,以标识它引用的表/模型(使用模型的关联ContentType;请参阅contenttypes)
示例:
class Foo(models.Model):
other_type = models.ForeignKey('contenttypes.ContentType', null=True)
other_id = models.PositiveIntegerField()
# Optional accessor, not a stored column
other = generic.GenericForeignKey('other_type', 'other_id')
这将允许您像ForeignKey一样使用other
来引用其他模型的实例。 (在后台,GenericForeignKey为您获取并设置other_type
和other_id
。)
要表示不是引用的数字,您可以将other_type
设置为无,并直接使用other_id
。在这种情况下,尝试访问other
将始终返回None,而不是引发DoesNotExist
(或由于ID冲突而返回非预期的对象)。
答案 5 :(得分:-1)
tablename = columnname.ForeignKey('table',null = True,blank = True,db_constraint = False)
在程序中使用它