多表关系
常见的数据模型关系有:
一对一(one-to-one),OneToOneField
一对多,多对一(one-to-many),ForeignKey
多对多(many-to-many),ManyToManyField
一对一
一对一:一个表中的每条记录对应另一个表中的每条记录,使用OneToOneField建立关系。
例如:一个人对应一个身份证号,一个身份证号也对应一个人
应用场景:当一个表想扩展字段,最常用的方式就是在这个表添加一个对一关系
一对一:创建模型关系
示例:定义一对一模型关系
class User (models.Model): user = models.CharField(max_length=30 , verbose_name="用户名" ) name = models.CharField(max_length=30 , verbose_name="姓名" ) sex = models.CharField(max_length=30 , verbose_name="性别" ) age = models.IntegerField(verbose_name="年龄" ) label = models.CharField(max_length=100 , verbose_name="标签" ) class IdCard (models.Model): number = models.CharField(max_length=20 , verbose_name="卡号" ) address = models.CharField(max_length=50 , default="北京" ) user = models.OneToOneField(User, on_delete=models.CASCADE)
一对一:增删改查
增:
方式1 : user_obj = User.objects.create(user='alan' ,name='阿兰' ,sex='女' ,age='25' ,label="运营,漂亮,喜欢购物" ) IdCard.objects.create(user=user_obj, number="456789" , address="北京" ) 方式2 : user = User() user.user='xiaoming' user.name = "阿兰" user.sex = '女' user.age = 25 user.label = "运营,漂亮,喜欢购物" user.save()
向已有用户添加身份证信息:
user_obj = User.objects.get(user="amei" ) IdCard.objects.create(user=user_obj, number="123456789" , address="北京" )
查:
反向查询:通过用户查到身份证信息(user->idcard)
user = User.objects.get(user="amei" ) print (user.idcard.number)print (user.idcard.address)
正向查询:从身份证表查用户(idcard->user)
idcard = IdCard.objects.get(user_id=1 ) print (idcard.user.user)print (idcard.user.name)
改:
User.objects.filter (user="amei" ).update(age="26" ) user_obj = User.objects.get(user="amei" ) user_obj.idcard.address="北京" user_obj.idcard.save() user_obj.age = 24 user_obj.save()
删:
User.objects.filter (user="alan" ).delete()
一对多
一对一是表与表之间的关系,而一对多、多对多是表与表中数据的关系
一对多:A表中的某个记录对应B表中的多条记录,使用ForeignKey建立关系。
例如:项目部署涉及表
一对多:一个项目有多个应用,一个应用只能属于一个项目
多对多:一个应用部署到多台服务器,一个服务器部署多个应用
一对多:创建模型关系
class Project (models.Model): name = models.CharField(max_length=30 ) describe = models.CharField(max_length=100 , null=True ) datetime = models.DateTimeField(auto_now_add=True ) def __str__ (self ): return self.name class Meta : db_table = 'project' verbose_name_plural = '项目' class App (models.Model): name = models.CharField(max_length=30 ) describe = models.CharField(max_length=100 , null=True ) datetime = models.DateTimeField(auto_now_add=True ) project = models.ForeignKey(Project, on_delete=models.CASCADE) def __str__ (self ): return self.name class Meta : db_table = 'app' verbose_name_plural = '应用' class Server (models.Model): hostname = models.CharField(max_length=30 ) ip = models.GenericIPAddressField() describe = models.CharField(max_length=100 , null=True ) def __str__ (self ): return self.hostname class Meta : db_table = 'server' verbose_name_plural = '服务器'
一对多:增删改查
向项目表添加已知的项目名称:
Project.objects.create(name="电商项目" ,describe="电商项目描述..." ) Project.objects.create(name="在线教育项目" ,describe="在线教育项目描述..." ) Project.objects.create(name="大数据项目" ,describe="大数据项目描述..." )
创建新应用并加入到项目中:
project_obj = Project.objects.get(name="电商项目" ) App.objects.create(name="product" ,describe="商品服务" ,project=project_obj)
注:操作模型类记得先导入 from myapp.models import Project,App
正向查询:通过应用名称查询所属项目(app->project)
查询某个应用所属项目: app = App.objects.get(name="product" ) app.project.name 查询所有应用所属项目: app_list = App.objects.all () for i in app_list: print (i.name, i.project.name, i.project.describe)
示例:
def release (request ): app = App.objects.all () return render(request, "release.html" , {"app" :app}) {% for i in app_list %} {{ i.id }} {{ i.name }} {{ i.describe }} {{ i.project.id }} {{ i.project.name }} {% endfor %}
反向查询:通过项目名称查询有哪些应用(project->app)
查询某个项目有哪些应用: project = Project.objects.get(name="电商项目" ) project.app_set.all () 查询所有项目有哪些引用: project = Project.objects.all () for i in project: print (i.name, i.app_set.all ())
示例:
def app (request ): project_list = Project.objects.all () return render(request, "app.html" , {"project_list" : project_list}) {% for i in project_list %} {{ i }} {% for x in i.app_set.all %} {{ x }} {% endfor %} {% endfor %}
多对多
多对多:A表中的某个记录对应B表中的多条记录,B表中的某个记录对应A表中多条记 录。使用ManyToManyField建立关系。
例如:一个应用部署到多台服务器,一个服务器部署多个应用
多对多:创建模型关系
示例:定义多对多模型关系
class Server (models.Model): hostname = models.CharField(max_length=30 ) ip = models.GenericIPAddressField() describe = models.CharField(max_length=100 , null=True ) app = models.ManyToManyField(App) def __str__ (self ): return self.hostname class Meta : db_table = 'server' verbose_name_plural = '服务器'
Django会自动创建一个表来管理多对多关系,称为中间表;这个中间表的名称使用多对多的 名称和包含这张表的模型的名称生成,也可以使用db_table选项指定这个中间表名称。
多对多:增删改查
添加服务器:
Server.objects.create(hostname="ec-test1" , ip="192.168.1.10" , describe="电商项目测试服务器1" ) Server.objects.create(hostname="ec-test2" , ip="192.168.1.11" , describe="电商项目测试服务器2" ) Server.objects.create(hostname="bigdata-test1" , ip="192.168.1.11" , describe="大数据项目测试服务器1" )
部署一个应用到指定服务器:
project_obj = Project.objects.get(name="电商项目" ) app = App.objects.create(name="portal" ,describe="前端服务" ,project=project_obj) server = Server.objects.get(hostname="ec-test1" ) server.app.add(app)
正向查询:查询服务器部署了哪些应用(server->app)
查询某台服务器部署了哪些应用: server = Server.objects.get(hostname="ec-test1" ) server.app.all () 查询所有服务器部署了哪些应用: server_list = Server.objects.all () for i in server_list: print (i.hostname, i.app.all ())
示例:
def server (request ): server_list = Server.objects.all () return render(request, "server.html" , {"server_list" : server_list}) {% for i in server_list %} {{ i }} {% for x in i.app.all %} {{ x.name }} {% endfor %} {% endfor %}
反向查询:查看某个应用部署到哪些服务器,通过项目名称查询有哪些应用(app->server)
查询某个应用部署到哪些服务器: app = App.objects.get(name="portal" ) app.server_set.all () 查询所有应用部署到哪些服务器: for i in app_list: print (i.name, i.server_set.all ())
示例:
def app_server (request ): app_list = App.objects.all () return render(request, "app.html" , {"app_list" : app_list}) {% for i in app_list %} {{ i }} {% for x in i.server_set.all %} {{ x }} {% endfor %} {% endfor %}
多对多:中间表关系操作
增加:
server = Server.objects.get(hostname="ec-test1" ) server.app.add(3 ) server.app.add(1 ,2 ,3 )
删除:
清空: