一个表的多个字段外端关联到同一个表
class Type(models.Model):
id = models.AutoField('id', primary_key=True)
name = models.CharField('name', max_length=16, unique=True)
type = models.CharField('type', max_length=16)
class Item(models.Model):
id = models.AutoField('id', primary_key=True)
name = models.CharField('name', max_length=32)
key = models.CharField('key', max_length=32)
type = models.ManyToManyField(Type)
class Rule(models.Model):
id = models.AutoField('id', primary_key=True)
name = models.CharField('name', max_length=16)
arg_1 = models.ForeignKey(Item, on_delete=models.CASCADE,null=True,related_name='arg_1')
arg_2 = models.ForeignKey(Item, on_delete=models.CASCADE,null=True,related_name='arg_2')
method = models.CharField('method', max_length=8)
class CustomReport(models.Model):
id = models.AutoField('id', primary_key=True)
name = models.CharField('name', max_length=16)
item = models.ManyToManyField(Item)
rule = models.ForeignKey(Rule, on_delete=models.CASCADE, null=True)
time_range = models.IntegerField('time_range', null=True)
period = models.IntegerField('period', null=True)
create_time = models.DateTimeField('create_time', auto_now_add=True)
update_time = models.DateTimeField('update_time', auto_now_add=True)
在arg_1,arg_2 设置外键的时候,
如果只设置models.ForeignKey(Item, on_delete=models.CASCADE
,
在迁移模型的时候会报错
[“ HINT: Add or change a related_name argument to the definition for 'Rule.arg_1 ' or 'Item.relay_to'.
原因是因为arg_1和arg_2字段指向同一个模型的外键关联名称产生了冲突。
解决:增加related_name属性,自定义关联名称
多对多
Item模型中。
type = models.ManyToManyField(Type)
CustomReport模型中
item = models.ManyToManyField(Item)
指定多对多字段关联的表模型,在完成迁移之后,在数据库中生成相应的中间表
CustomReport_item
Item_type
orm操作:
查:
report.item.all()获取report对象关联的所有item对象,可以根据关系不停的使用嵌套进行查值。
增:
增加的是一个列表,列表中可以是对象,也可以是对象的id值,
- 添加对象
report.item.add(item对象) 完成多外键的添加。 - 直接使用item赋值
report.item = Item.objects.all()[0:3]
这种方式是网上查的,但是我在实际使用时插入不了,提示queryset对象不能插入 - 直接使用item的id列表插入
item_ids 是一个id的列表对象
report.item.set(item_ids)
除了使用orm自动生成的中间表,还可以自定义一个中间表,这样就可以方便的进行数据的CRUD了。
from django.db import models
class Books(models.Model):
""" 书籍表 """
title = models.CharField(max_length=32) # 书籍名称
# 外键关联,法1, 不推荐
# 有啥区别,?字符串和不是字符串的有区别?
# publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) # 绑定外键,关联出版社
# 外键关联,法2, 推荐
publisher = models.ForeignKey('Publisher', on_delete=models.CASCADE)
# 外键关联, 指点关联字段
# publisher = models.ForeignKey('Publisher', on_delete=models.CASCADE, to_field='name') # 关联指定字段
def __str__(self):
return self.title
class Author(models.Model):
""" 作者表 """
name = models.CharField(max_length=32, unique=True) # 作者名,并建立唯一约束
book = models.ManyToManyField(to='Books', through='AuthorToBook') # 关联书籍表,表示当前表与书籍表建立多对多的关系
def __str__(self):
return self.name
class AuthorToBook(models.Model):
""" 第三张表,关联作者和书籍 """
author = models.ForeignKey('Author')
book = models.ForeignKey('Books')
date = models.DateField()
使用定义的中间表来进行增加数据
AuthorToBook.objects.create(book_id=book_obj.id, author_id=author_obj.id, date='2019-05-21')
多表关联查询
查询一对多的关系
-
django默认每个主表对象都有一个外键的属性,可以通过这个属性查询所有属于主表的字表信息,查询方法
主表.字表_set()
,返回一个requeryset对象
tom.Car_set().all()查询tom的所有车信息 -
通过在外键中设置related_name属性值即可获取数据
tom.cars.all() -
通过@property装饰器在model中预定义实现
tom.all_cars
多对多的关联对象删除
通过一个对象(非queryset)来查询所关联的多端对象,然后可以将对象删除,
gr = GeneralReport.objects.filter(id=report_id).first()
gr.config.all().delete() #查询所有config对象,删除
gr.filters.all().delete() #查询所有filters对象,删除
gr.delete() # 最后删除源数据
res = {'status': True, 'message': '删除成功'}