我有一个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')
答案 0 :(得分:2)
归结为:您需要一个表 BC 来存储 B 和 C 之间的关系。表 A 然后只能通过中间m2m表 ABC (或沟渠ABC,无法通过在线工具绘制m2m)来选择这些关系。我想我在这张照片中混淆了B和C,根据B或C是否持有ForeignKey来交换它们 如果我错了,请更正!
答案 1 :(得分:2)
我不确定您要在何处以及如何验证您的数据。所以我只是发布了一个方法,可以验证项目是否可以根据您的具体检查链接到设备。
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')
结帐docs
现在,当您链接设备和项目时,您也将明确添加区域ID。在现在添加之前,您可以根据相关区域检查项目是否有效。