先来区分一下什么是一对一、多对多
一对一:子表从母表中选出一条数据一一对应,母表中选出来一条就少一条,子表不可以再选择母表中已被选择的那条数据;
一对多:子表从母表中选出一条数据一一对应,但母表的这条数据还可以被其他子表数据选择;
共同点是在admin中添加数据的话,都会出现一个select选框,但只能单选,因为不论一对一还是一对多,自己都是“一”;
多对多总结:
比如有多个孩子,和多种颜色;
每个孩子可以喜欢多种颜色,一种颜色可以被多个孩子喜欢,对于双向均是可以有多个选择;
应用场景
一对一:一般用于某张表的补充,比如用户基本信息是一张表,但并非每一个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登录信息的表,与用户信息进行一对一的关联,可以方便的从子表查询母表信息或反向查询;
外键:有很多的应用场景,比如每个员工归属于一个部门,那么就可以让员工表的部门字段与部门表进行一对多关联,可以查询到一个员工归属于哪个部门,也可反向查出某一部门有哪些员工;
多对多:如很多公司,一台服务器可能会有多种用途,归属于多个产品线当中,那么服务器与产品线之间就可以做成对多对,多对多在A表添加manytomany字段或者从B表添加,效果一致;
demo 如下:

class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32,null=True,default="SA") #一对多ForeignKey class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4", db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id') class hosts(models.Model): nid = models.AutoField(primary_key=True) hostname=models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4") port = models.IntegerField() #多对多, ManyToManyField(无法对第三张表进行直接操作) class Application(models.Model): name = models.CharField(max_length=32) r = models.ManyToManyField("hosts") #多对多,可以对第三表直接进行操作 class HostToapp(models.Model): hobj = models.ForeignKey(to="hosts",to_field="nid") aobj = models.ForeignKey(to="Application", to_field="id")
数据库操作
app_name = request.POST.get('app_name') obj = models.Application.objects.create(name=app_name) host_list = request.POST.getlist('host_list') obj.r.add(*host_list) obj.r.remove(1) obj.r.remove(*host_list) obj.r.set(*host_list) print(obj.r.all())