..

Django ORM的多对多关系 (每个关系有附加的属性)

最近写公司的业务代码, 碰到这么一个问题:
一个User对应多个Account, 而每个Account又可以分享给多个user, 典型的多对多的关系.
但问题在于每个关系, 都有一个permissionsharing的属性: 0: 只读 / 1: 读写 / 2: 自身创建.
晚上我尝试着用django的orm来实现这个需求.

Model的定义:

from django.db import models

from django.db import models


class Account(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name


class User(models.Model):
    name = models.CharField(max_length=128)
    accounts = models.ManyToManyField(Account, through='PermissionSharing')

    def __str__(self):
        return self.name


class PermissionSharing(models.Model):
    account = models.ForeignKey(Account, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    permission = models.SmallIntegerField()

多对多关系的创建:

user –> account[permission]
u1 –> a1[1], a2[2]
u2 –> a1[2], a3[2]

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'manytomany.settings')

import django
django.setup()

from a1.models import Account, User, PermissionSharing

a1 = Account.objects.create(name='a1')
a2 = Account.objects.create(name='a2')
a3 = Account.objects.create(name='a3')

u1 = User.objects.create(name='u1')
u2 = User.objects.create(name='u2')

PermissionSharing.objects.create(user=u1, account=a1, permission=1)
PermissionSharing.objects.create(user=u1, account=a2, permission=2)
PermissionSharing.objects.create(user=u2, account=a1, permission=2)
PermissionSharing.objects.create(user=u2, account=a3, permission=2)

相互获取对方set的方法和filter方法:

# 相互获取对应的set
print(u1.accounts.all())
print(a1.user_set.all())

# filter
print(User.objects.filter(accounts__name='a1', permissionsharing__permission=1))
print(Account.objects.filter(user=u1, permissionsharing__permission=1))

# 获取relation的属性(extra field: permission)
# 1)
ps = PermissionSharing.objects.get(user=u1, account=a1)
print(ps.permission)
# 2)
ps = a1.permissionsharing_set.get(user=u1)
ps = u1.permissionsharing_set.get(account=a1)
print(ps.permission)


# clear
u1.accounts.clear()

Account.objects.all().delete()
User.objects.all().delete()
PermissionSharing.objects.all().delete()
EOF