如何通过单个外键创建记录的联接表,其中使用MySQL或Django在第二列的值上对每一列进行过滤

问题描述 投票:0回答:1

我正在使用Django 2.2来查看和编辑MySQL表。我有一个名为“ Disorder”的表,该表在Django中表示如下:

class Disorder(models.Model):
    disorder_name = models.CharField(
        max_length=255,
        primary_key=True
    )

    disorder_type_choices = [
        ('Disease', 'Disease'),
        ('Syndrome', 'Syndrome'),
    ]

    disorder_type = models.CharField(
        max_length=10,
        choices=disorder_type_choices,
        blank=True,
        null=True
    )

    class Meta:
        managed = False
        db_table = 'Disorder'

    def __str__(self):
        return f"{self.disorder_name}

我现在想创建一个联接表,其中'disorder_type = Disease'的条目可以与'disorder_type = Syndrome'相关联。该连接表将具有三列,一个自动递增的整数外键,一个校正子和一个相关的疾病。

我已经尝试了几种在MySQL级别和Django级别生成此代码的方法。我想在MySQL级别强制执行约束会更好(尽管我现在仅使用Django admin添加到数据库中),并且虽然很容易从连接表中对同一外键进行两个引用(请参见下文),但我无法强制执行这些列上的'WHERE'约束迫使'disease'是一种疾病,其中disorder_type =疾病'syndrome'是一种疾病,其中疾病_type =综合征。

CREATE TABLE `DiseaseSyndromeLink` (
`ds_id` int NOT NULL AUTO_INCREMENT,
    `disease` VARCHAR(255) NOT NULL,
`syndrome` VARCHAR(255) NOT NULL,
    PRIMARY KEY (`ds_id`),
    FOREIGN KEY (disease) REFERENCES disorder(disorder_name),
    FOREIGN KEY (syndrome) REFERENCES disorder(disorder_name)
)

我接下来考虑仅通过模型的Django表示来强制执行关系。我尝试使用ValidationErrors和CheckConstraints实现此目标,但没有任何进展(请参见下文):

class Diseasesyndromelink(models.Model):
    ds_id = models.AutoField(primary_key=True)
    disease = models.ForeignKey('Disorder', models.DO_NOTHING, db_column='disease', related_name='disease')
    syndrome = models.ForeignKey('Disorder', models.DO_NOTHING, db_column='syndrome', related_name='syndrome')

    class Meta:
        managed = False
        db_table = 'diseasesyndromelink'
        constraints = [
            models.UniqueConstraint(
                fields=['syndrome', 'disease'],
                name='uq_syndrome_disease'
            ),
            models.CheckConstraint(
                check=(Q(syndrome__disorder_type__eq="Syndrome")),
                name='ck_syndrome_is_syndrome'
            ),
            models.CheckConstraint(
                check=(Q(disease__disorder_type__eq="Disease")),
                name='ck_disease_is_disease'
            )
        ]

这将产生以下错误:

WARNINGS:
models_app.DiseaseSyndromeLink: (models.W027) MySQL does not support check constraints.
    HINT: A constraint won't be created. Silence this warning if you don't care about it.
models_app.PatientClinicalFeatures.cfd: (fields.W342) Setting unique=True on a ForeignKey has the same effect as using a OneToOneField.
    HINT: ForeignKey(unique=True) is usually better served by a OneToOneField.

最后,我想知道是否有可能用'选择'表示联接表中的'疾病'和'综合征'字段(如原始Disorder.disorder_type字段中所示)。如果我可以从Disorder表中提取出“疾病”和“综合征”的过滤列表,则可以将它们直接传递给模型,但我无法为此生成任何有用的Python代码,并且怀疑它与在MySQL级别修复。话虽这么说,在MySQL级别上执行的所有操作也都必须在Django模型中表示,但我在YouTube教程的文档中没有看到类似此问题的内容。

对于这些解决方案中的任何一种是否是解决问题的适当方法以及如果可以的话,我将不胜感激。

感谢您的时间!

python mysql django foreign-keys constraints
1个回答
0
投票

正如我所看到的,您的MYSQL语句有点奏效,所以您所需要做的就是以与您相同的方式向模型添加外键。尽管这一次,您将设置'null = True',如果您具有唯一值,则将'unique = True'设置为空列。现在,您必须在添加数据时在应用程序逻辑中实现其余部分,还必须了解“疾病类型所在”等标准。但是,当您从数据库中读取时,Django会自动进行预取相关。查询读取数据的示例。

data=Diseasesyndromelink.objects.filter(disease__feild="query")
print(data.disease) #your foreign key object is prefetched here already.

查看文档以获取更多示例。https://docs.djangoproject.com/en/3.0/topics/db/models/

© www.soinside.com 2019 - 2024. All rights reserved.