Django ORM ManyToManyField

Django 官网对 ManyToManyField 操作的例子写的比较少,正好用到了就来总结下,先来定义下 Model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django.db import model

class Product(models.Model, ModelMixin): # 产品表
name = models.CharField(max_length=64)

class Meta:
db_table = 'products'

class Company(models.Model, ModelMixin): # 公司表
products = models.ManyToManyField(Product)
name = models.CharField(max_length=64)

class Meta:
db_table = 'companies'

如果执行 manage.py migrate 后会自动多生成一个 companies_products 的关系表。

关系维护

  • 创建关联关系

    1
    2
    3
    4
    5
    6
    7
    company = Company.objects.get(pk=1)
    company.products.add(1)
    company.products.add(2, 3)
    # 反向操作
    product = Product.objects.get(pk=1)
    product.company_set.add(1)
    product.company_set.add(2, 3)
  • 设置关联关系

    1
    2
    company.products.set([2, 3])
    product.company_set.set([1, 3])
  • 关联创建

    1
    2
    company = Company.objects.get(pk=1)
    company.products.create(name='Model 3')
  • 移除关联关系

    1
    2
    company.products.remove(1, 3)
    product.company_set.remove(2)
  • 清除关联关系

    1
    2
    company.products.clear()
    product.company_set.clear()

关联查询

  • 查询某公司关联的所有产品

    1
    2
    company = Company.objects.get(pk=1)
    company.products.all()

    等价于

    1
    Product.objects.filter(company__id=1)
  • 查询拥有某产品的所有公司

    1
    2
    product = Product.objects.get(pk=1)
    product.company_set.all()

    等价于

    1
    Company.objects.filter(products__id=1)

获取关系表对象

如上例子可以通过 Company.products.through 获取关系表对象,例如

1
2
3
4
5
6
rel = Company.products.through.objects.first()
rel.product_id
rel.company_id
# out
2
1