Django ManyToMany验证约束
我有一个ManyToMany链接和一个链接三个对象的外键。
[A]> - <[B]> --- [C]
A可以属于许多B,反之亦然。 但是,A只能属于具有相同父 C的B对象。
我试图在模型的clean()
方法中做一些事情。 我使用的是Django Rest Framework,并没有ModelForms或类似的东西。 我还没有弄清楚
简化的示例代码
class Device(models.Model):
name = models.CharField(max_length=20)
projects = models.ManyToManyField(Project, 'devices')
details = models.CharField(max_length=200)
serial = models.CharField(max_length=20)
address models.GenericIPAddressField(default="0.0.0.0")
port = models.IntegerField(default=3000)
jumpers = models.IntegerField(default=0)
install_date = models.DateField(blank=True, null=True)
class Project(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=250)
area = models.ForeignKey(Area)
class Area(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=250)
owner = models.CharField(max_length=20) # microservice doesn't have owner group - field in JWT
串行器
class AreaSerializer(serializers.ModelSerializer):
class Meta:
model = Area
fields = ('name', 'description', 'owner')
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = ('id', 'name', 'description', 'area')
class DeviceSerializer(serializers.ModelSerializer):
class Meta:
model = Device
fields = ('id', 'name', 'projects', 'details', 'serial',
'address', 'port', 'jumpers', 'install_date')
我不确定你想在哪里以及如何验证你的数据。 所以我只是发布一个方法,可以验证项目是否可以链接到设备或不是基于您的具体检查。
def validate_project(device, project):
projects = device.projects.all()
areas = set(projects.values_list('area', flat=True))
if len(areas) > 1:
raise serializers.ValidationError('projects are not valid')
return areas.pop() == project.area_id
编辑:
您必须使用中间模型来存储设备和项目之间的关系。
class Membership(models.Model):
device = models.ForeignKey(Device, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
area = models.ForeignKey(Area, on_delete=models.CASCADE)
使用上述成员模型来存储多对多关系。
在您的设备模型上使用此字段来定义多对多关系。
projects = models.ManyToManyField(Project, through='Membership')
检出文档
现在,当您链接设备和项目时,您也将明确添加区域ID。 现在添加之前,您可以根据相关区域检查项目是否有效。
(忽略不可靠的字段类型,cba)
它归结为:你需要一个表BC来存储B和C之间的关系。 然后,表A只能通过中间的m2m表ABC (或沟渠ABC,无法弄清楚如何用在线工具绘制m2m)从这些关系中选择。 我想我在这幅图中混合了B和C,根据B或C是否拥有ForeignKey来交换它们。
如果我错了,请纠正!