多对多

一个表的多个字段外端关联到同一个表

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值,

  1. 添加对象
    report.item.add(item对象) 完成多外键的添加。
  2. 直接使用item赋值
    report.item = Item.objects.all()[0:3]
    这种方式是网上查的,但是我在实际使用时插入不了,提示queryset对象不能插入
  3. 直接使用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')

多表关联查询

查询一对多的关系

  1. django默认每个主表对象都有一个外键的属性,可以通过这个属性查询所有属于主表的字表信息,查询方法主表.字表_set(),返回一个requeryset对象
    tom.Car_set().all()查询tom的所有车信息

  2. 通过在外键中设置related_name属性值即可获取数据
    tom.cars.all()

  3. 通过@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': '删除成功'}

https://www.cnblogs.com/lxfpy/p/10890045.html

原文地址:https://www.cnblogs.com/cizao/p/11481902.html