django多表操作
1540字约5分钟
2024-09-29
多表关系
常见的数据模型关系有:
- 一对一(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 = 'operation'
        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)  # 将应用id3关联该服务器
server.app.add(1,2,3)  # 将应用id1、2、3关联该服务器删除:
server.app.remove(3) # 将应用id3与该服务器取消关联清空:
server.app.clear() # 将该服务器取消所有应用关联