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来存储BC之间的关系。 然后,表A只能通过中间的m2m表ABC (或沟渠ABC,无法弄清楚如何用在线工具绘制m2m)从这些关系中选择。 我想我在这幅图中混合了B和C,根据B或C是否拥有ForeignKey来交换它们。
如果我错了,请纠正!

链接地址: http://www.djcxy.com/p/41209.html

上一篇: Django ManyToMany Validation Constraint

下一篇: Using nbind with Angular 5 and TypeScript