related_name和related_query_name属性

在Django模型继承中,假如在外键或多对多字段中使用了related_name属性或related_query_name属性,则必须为该字段提供一个独一无二的反向名字和查询名字。但是,这样在抽象基类中一般会引发问题,因为基类中的字段都被子类继承并且保持了同样的值,这其中当然也包括related_name属性和related_query_name属性。

为了解决上述问题,当在抽象基类中(也只能是在抽象基类中)使用related_name属性和related_query_name属性时,部分值需要包含"%(app_label)s"和"%(class)s",具体说明如下:

  • %(class)s:用该字段子类的小写类名替换。
  • %(app_label)s:用小写的、包含子类的应用名替换。每个安装的应用名必须唯一,应用内的每个模型类名也必须唯一,因此替换后的名字也是唯一的。

关于related_name属性或related_query_name属性的使用,示例代码如下:

【代码3-19】

复制代码
01  # --- common app --- #
02  # common/models.py:
03  
04  from django.db import models
05  
06  class Base(models.Model):
07      m2m = models.ManyToManyField(
08          OtherModel,
09          related_name="%(app_label)s_%(class)s_related",
10          related_query_name="%(app_label)s_%(class)ss",
11      )
12  
13      class Meta:
14          abstract = True
15  
16  class ChildA(Base):
17      pass
18  
19  class ChildB(Base):
20      pass
21  
22  # --- another app --- #
23  # another/models.py:
24  
25  from common.models import Base
26  
27  class ChildB(Base):
28      pass

【代码分析】

在第01~20行代码中,定义了第一个Python应用common app,具体内容说明如下:

  • 在第06~14行代码中,定义了一个抽象基类Base:
  1. 在第07~11行代码中,定义了一个多对多属性m2m,并使用了related_name属性和related_query_name属性。
  2. 在第13、14行代码中,在Meta类中添加了属性"abstract=True",表明Base类为抽象 基类。
  • 在第16、17行和第19、20行代码中,定义了两个继承自抽象基类Base的子类ChildA和ChildB,具体内容说明如下:
  1. common.ChildA.m2m字段的反转名是common_childa_related,反转查询名是common_childas。
  2. common.ChildB.m2m字段的反转名是common_childb_related,反转查询名是common_childbs。

在第22~28行代码中,定义了第二个Python应用another app,具体内容说明如下:

  • 在第27、28行代码中,定义了一个继承自抽象基类Base的子类ChildB。其中,another.ChildB.m2m字段的反转名是another_childb_related,反转查询名是another_childbs。

如何使用"%(class)s"和"%(app_label)s"构建关联名字和关联查询名,取决于设计人员。不过,如果在设计时忘了使用"%(class)s"和"%(app_label)s",那么Django会在执行系统检查或运行迁移时抛出错误。如果设计时未指定抽象基类中的related_name属性,那么默认的反转名会是子类名后接"_set"。

本文节选自《Django 5企业级Web应用开发实战(视频教学版)》,获出版社和作者授权发布。

相关推荐
数据智能老司机5 小时前
CockroachDB权威指南——CockroachDB SQL
数据库·分布式·架构
数据智能老司机5 小时前
CockroachDB权威指南——开始使用
数据库·分布式·架构
松果猿6 小时前
空间数据库学习(二)—— PostgreSQL数据库的备份转储和导入恢复
数据库
无名之逆6 小时前
Rust 开发提效神器:lombok-macros 宏库
服务器·开发语言·前端·数据库·后端·python·rust
s9123601016 小时前
rust 同时处理多个异步任务
java·数据库·rust
数据智能老司机6 小时前
CockroachDB权威指南——CockroachDB 架构
数据库·分布式·架构
hzulwy6 小时前
Redis常用的数据结构及其使用场景
数据库·redis
程序猿熊跃晖7 小时前
解决 MyBatis-Plus 中 `update.setProcInsId(null)` 不生效的问题
数据库·tomcat·mybatis
Three~stone8 小时前
MySQL学习集--DDL
数据库·sql·学习
Qi妙代码8 小时前
MYSQL基础
数据库·mysql·oracle