Django中的循环DB关系

Django中的循环DB关系,django,database,relationship,circular-dependency,Django,Database,Relationship,Circular Dependency,我有以下模型(活动/models.py) …这导致了以下数据库(sqlite3): 逻辑如下: 活动由测试组成 一个活动可以运行多次(活动运行)并产生测试结果(测试运行) 对于每个活动运行,将从测试表中收集与测试相关的信息 显然,存在循环关系,数据库的完整性仅由应用程序来保证 但是,从数据库架构师的角度来看,这种循环关系是不正确的,因为它会导致完整性问题: 在SQL中直接或通过django管理模块,可以在campaign_testrun中创建不在campaign_tests表中的测试 出

我有以下模型(活动/models.py)

…这导致了以下数据库(sqlite3):

逻辑如下:

  • 活动由测试组成
  • 一个活动可以运行多次(活动运行)并产生测试结果(测试运行)
  • 对于每个活动运行,将从测试表中收集与测试相关的信息
显然,存在循环关系,数据库的完整性仅由应用程序来保证

但是,从数据库架构师的角度来看,这种循环关系是不正确的,因为它会导致完整性问题:

  • 在SQL中直接或通过django管理模块,可以在campaign_testrun中创建不在campaign_tests表中的测试

出于上述原因,解决方案是将活动\u testrun与活动\u活动\u测试直接链接。然而,我认为在Django是不可能的

如果您有任何想法如何处理这个问题,欢迎发表评论

提前感谢您的帮助。

使用ManyToManyField

这允许您使用自定义模型,并在FKs、M2M等中引用它

还要注意的是,您可以引用类名,即ForeignKey('SomeClass'),这样可以毫无问题地实现循环关系

欢迎来到Django,祝您旅途愉快B)

使用ManyToManyField

这允许您使用自定义模型,并在FKs、M2M等中引用它

还要注意的是,您可以引用类名,即ForeignKey('SomeClass'),这样可以毫无问题地实现循环关系


欢迎来到Django,祝你旅途愉快B)

“但是,我认为在Django不可能。”为什么?您尝试了什么?与以下问题无关:您是如何获得数据库布局的出色表示的?@clentford:我使用textedit手动完成了此DB表示:P@jpic:为什么?因为理想的方法是与campaigns_campaign_tests Manytomy表建立关系,这在Django中似乎不可能,对吧?我试了什么?我的问题中指定的模型:)“但是,我认为在Django不可能。”为什么?您尝试了什么?与以下问题无关:您是如何获得数据库布局的出色表示的?@clentford:我使用textedit手动完成了此DB表示:P@jpic:为什么?因为理想的方法是与campaigns_campaign_tests Manytomy表建立关系,这在Django中似乎不可能,对吧?我试了什么?我的问题中指定的模型:)
from django.db import models
from django.contrib.auth.models import User

class Module(models.Model):
    name = models.CharField(max_length=20)
    def __unicode__(self):
        return self.name

class TestType(models.Model):
    name = models.CharField(max_length=20)
    def __unicode__(self):
        return self.name

class Test(models.Model):
    PROTO_CHOICES = (
        ('TCP','tcp'),
        ('UDP','udp'),
    )
    module = models.ForeignKey(Module)
    testtype = models.ForeignKey(TestType)
    name = models.CharField(max_length=50, unique=True)
    port = models.IntegerField(blank=True, null=True)
    proto = models.CharField(max_length=3, blank=True, choices=PROTO_CHOICES)
    payload = models.TextField()
    sig_match = models.TextField(blank=True)
    def __unicode__(self):
        return self.name

class Campaign(models.Model):
    name = models.CharField(max_length=50, unique=True)
    tests = models.ManyToManyField(Test)
    updated = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, editable=False)
    def __unicode__(self):
        return self.name

class CampaignRun(models.Model):
    campaign = models.ForeignKey(Campaign)
    name = models.CharField(max_length=50, unique=True)
    run_start = models.DateTimeField()
    run_end = models.DateTimeField()
    updated = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(User, editable=False)
    class Meta:
    def __unicode__(self):
        return self.name

class TestRun(models.Model):
    campaignrun = models.ForeignKey(CampaignRun)
    test = models.ForeignKey(Test)
    test_start = models.DateTimeField()
    test_end = models.DateTimeField()
    alert = models.TextField(blank=True)
    flag = models.IntegerField(blank=True, null=True)
                                                                       +-----------------------------+
                                                                       |                             |
   +---------------------------+     +------------------------------+  |     +--------------------+  |
   | campaigns_testrun         |     | campaigns_test               |  |     | campaigns_module   |  |
   +----------------+----------+     +----------------+-------------+  |     +------+-------------+  |
   | id             | INT      |  +--| id             | INT         |--+  +--| id   | INT         |  |
+--| campaignrun_id | INT      |  |  | module_id      | INT         |-----+  | name | VARCHAR(20) |  |
|  | test_id        | INT      |--+  | testtype_id    | INT         |--+     +------+-------------+  |
|  | test_start     | DATETIME |     | name           | VARCHAR(50) |  |                             |
|  | test_end       | DATETIME |     | port           | INT         |  |     +--------------------+  |
|  | alert          | TEXT     |     | proto          | VARCHAR(3)  |  |     | campaigns_testtype |  |
|  | flag           | INT      |     | payload        | TEXT        |  |     +------+-------------+  |
|  +----------------+----------+     | sig_match      | TEXT        |  +-----| id   | INT         |  |
|                                    +----------------+-------------+        | name | VARCHAR(20) |  |
|                                                                            +------+-------------+  |
|                                                                                                    |
|  +------------------------+                                +--------------------------+            |
|  | campaigns_campaignrun  |     +--------------------+     | campaigns_campaign_tests |            |
|  +-------------+----------+     | campaigns_campaign |     +-------------+------------+            |
+--| id          | INT      |     +------+-------------+     | id          | INT        |            |
   | campaign_id | INT      |-----| id   | INT         |-----| campaign_id | INT        |            |
   | name        | INT      |     | name | VARCHAR(50) |     | test_id     | INT        |------------+
   | run_start   | DATETIME |     +------+-------------+     +-------------+------------+
   | run_end     | DATETIME |     
   +-------------+----------+