Django ForeignKey与数据库的FOREIGN KEY约束详解
数据库在高并发的场景下使用外键约束会有锁问题并且使用外键会增加运维成本,所以很多公司都规定生产环境的数据库禁止使用外键。
那么不使用外键约束的情况下使用DjangoORM如何实现关联查询两个表呢?这曾是困扰我很久的一个问题,今天终于找到了答案,写出来分享一下。
Django的ForeignKey和数据库的FOREIGNKEY并不一样。Django的ForeignKey是一种逻辑上的两个表的关联关系,可以指定是否使用数据库的FOREIGNKEY约束。
在开头提到的场景下,我们可以这样创建两个表对应的Model,以省和市的关联举例:
#demo/models.py fromdjango.dbimportmodels classProvince(models.Model): name=models.CharField(max_length=16) def__unicode__(self): returnself.name classCity(models.Model): name=models.CharField(max_length=16) province=models.ForeignKey(Province,null=True,on_delete=models.SET_NULL, related_name='cities',db_constraint=False) def__unicode__(self): returnself.name
以上的models.py在执行migrate时生成的SQL如下(MySQL数据库):
CREATETABLE`demo_city`(`id`integerAUTO_INCREMENTNOTNULLPRIMARYKEY,`name`varchar(16)NOTNULL); CREATETABLE`demo_province`(`id`integerAUTO_INCREMENTNOTNULLPRIMARYKEY,`name`varchar(16)NOTNULL); ALTERTABLE`demo_city`ADDCOLUMN`province_id`integerNULL; CREATEINDEX`demo_city_province_id_50fffd49`ON`demo_city`(`province_id`);
如果ForeignKey不添加db_constraint=False参数,会在数据库中使用外键约束,生成以下SQL:
ALTERTABLE`demo_city`ADDCONSTRAINT`demo_city_province_id_aff53934_fk_key_province_id`FOREIGNKEY(`province_id`)REFERENCES`demo_province`(`id`);
另外,ForeignKey的on_delete参数默认为on_delete=models.CASCADE,表示使用数据库的级联删除,使用on_delete=models.SET_NULL可以使删除Province时将关联的City表对应的province_id值设为NULL
使用这种方式不会破坏Django的反向关联查询,以下查询仍然会返回正确的结果:
Province.objects.filter(cities__name='xxx')
实际执行的SQL为一个InnerJoin查询:
SELECT`demo_province`.`id`,`demo_province`.`name`FROM`demo_province`INNERJOIN`demo_city`ON(`demo_province`.`id`=`demo_city`.`province_id`)WHERE`demo_city`.`name`=xxx;
补充知识:关于Django模型中中定义auto_now=True数据库中的时间并没有自动更新
django的orm关于更新数据库的方法有update和save两种方法。
前提在模型中设置了auto_now=True时间戳属性,为了方便数据库自动更新时间,而
使用update更新的记录,数据库中并没有自动更新,达到我的需求。
auto_now=True自动更新,有一个条件,就是要通过django的model层。
如create或是save方法。
如果是filter之后update方法,则直接调用的是sql,不会通过model层,
所以不会自动更新此时间。所以使用save方法更新才能达到我的需求。
以上这篇DjangoForeignKey与数据库的FOREIGNKEY约束详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。