1. ManyToManyField (参考:Django Documentation Release 4.1.4)
- 类定义
class ManyToManyField(to, **options) - 使用说明
A many-to-many relationship. Requires a positional argument: the class to which the model is related, which works exactly the same as it does for ForeignKey, including recursive and lazy relationships. Related objects can be added, removed, or created with the field’ s RelatedManager.
多对多(many-to-many)关系,所需位置参数:与model(模型)相关的类,其工作方式与ForeignKey相同,包括递归和惰性关系。相关对像可以通过字段的RelatedManager进行添加、删除或创建。 - to
models.ManyToManyField("self")
When Django processes this model, it identifies that it has a ManyToManyField on itself.
当Django处理这个模型时,被识别为自身的ManyToManyField。 - 数据库定义
Database Representation Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship. By default, this table name is generated using the name of the many-to-many field and the name of the table for the model that contains it. Since some databases don’ t support table names above a certain length, these table names will be automatically truncated and a uniqueness hash will be used, e.g. author_books_9cdf. You can manually provide the name of the join table using the db_table option.数据库后台表示,Django创建中间连接表来表示多对多关系。默认的表名使用模型包含的多对多字段的名称和表名生成。由于某些数据库不支持超长表名,这些表名将被自动截断,并使用唯一散列。可以使用表选项手工提供联接表名。
-
Options(字典变量)
- related_name,关联对像返回的关联名
- related_query_name,来自目标模型的反过滤名
- limit_choices_to,字段可用选项(字典类型)
- symmetrical
The ManyToManyField is assumed to be symmetrical –that is, if I am your friend, then you are my friend. If you do not want symmetry in many-to-many relationships with self, set symmetrical to False. This will force Django to add the descriptor for the reverse relationship, allowing ManyToManyField relationships to be non-symmetrical.
假设ManyToManyField是对称的 -- 也就是说,如果我是你的朋友,那么你也是我的朋友。如果您不希望多对多关系中的自对称,设置symmetrical为False。这样Django为此反向关系添加描述,允许ManyToManyField关系是非对称的。
- through,指定要使用的特定模型(中间表)
- through_fields,使用through时使用,确认所使用的表中字段,建立many-to-many关系,field应为关连表的外键
- db_table,存储many-to-many数据的表名,不指定时自动关联自身模型表及字段
- db_constraint,控制是否创建交互表之间的外键约束,默认True
- swappable,交换模型下控制迁移框架的响应是否认配置进行,默认为 True
2. 实例
- 表 Table
- User 用户表:user_name, user_technique
- Technique 技能表:tech_name, tech_typeclass User(models.Model): user_name = models.CharField('User', max_length=50,)user_technique = models.ManyToManyField(Technique,blank=True) def tech_list(self):return ', '.join([i.tech_name for i in self.user_technique.all()])def __str__(self):return self.user_nameclass Meta:managed = Falsedb_table = 'user'
- User_user_technique,User 与 Techique关联表:technique_id, user_idclass Technique(models.Model): tech_name = models.CharField('TechniqueName', max_length=50, )tech_type = models.CharField('TechniqueType', max_length=20, choices=chol.techtype_list, )def __str__(self):return self.tech_namedef user_list(self):return ', '.join([i.user_name_id for i in self.user_set.all()])class Meta:managed = Falsedb_table = 'technique'
约束:User表通过user_technique与Technique表的tech_name关联,多对多关系:一个user可以拥有多项technique,一项technique可以属于多个不同的user - 表Model特别说明
# user table# 通过User_user_technique表形成manytomany关系user_technique = models.ManyToManyField(Technique,blank=True)# user表中user_technique 与 technique表中tech_name关联,定义新的字段tech_list列表显示user所拥有的techinque,添加到Admin的userAdmin的list_displaydef tech_list(self):return ', '.join([i.tech_name for i in self.user_technique.all()])# technique table# 反向访问user表,定义新字段user_list列表显示technique所归属的user,添加到Admin的techniqueAdmin的list_displaydef user_list(self):return ', '.join([i.user_name_id for i in self.user_set.all()])
- 界面效果
4. 关于through 和 through_field (待深入学习)
一般通过系统自动生成的manytomany关系可以满足基本的需要,如果有特殊要求可以通过自定义的关联关系实现特定要求。
# 自定义manytomany关联te_check = models.ManyToManyField('self',through='relationship', # 自定义关联表symmetrical=False,through_fields=('user_name', 'tech_name',), # 自定义表字段related_name='tech_name')
3. Errors List
- (admin.E109) The value of 'list_display[10]' must not be a ManyToManyField.
admin.py中的fileld_list列表中,ManyToManyField字段不能显示在内 - because that field manually specifies a relationship model
通过系统自动生成的manytomany关系的field无法再使用自动义的第 3 张关联表进行manatomany匹配,字段必须重新定义并与自定义的第 3 张表关联
4. 参考
Django Documentation 4.1.4