Django模型 - 如何定义外键引用另一个表?

时间:2017-06-21 22:04:55

标签: django django-models django-queryset

我正在使用legay数据库,因此我必须设置managed = False,这意味着我无法更新数据库架构。

我尝试做的是根据项目ID选择分支。理想情况下,在分支表中,它应该有一个project_id作为外键,但以前的系统设计是另一个表(branches_projects)存储这种关系。

我已经能够使用https://docs.djangoproject.com/en/1.11/topics/db/sql/#django.db.models.Manager.raw解决一些问题。 raw()将返回一个RawQuerySet,这是不理想的。

我想知道是否有一种方法可以在我的分支表中定义一个外键,即project_id,但是引用/链接到branches_projects表?

class Branches(models.Model):
    name = models.CharField(max_length=128)
    branchpoint_str = models.CharField(max_length=255)
    dev_lead_id = models.IntegerField(blank=True, null=True)
    source = models.CharField(max_length=255)
    state = models.CharField(max_length=255)
    kind = models.CharField(max_length=255)
    desc = models.TextField(blank=True, null=True)
    approved = models.IntegerField()
    for_customer = models.IntegerField()
    deactivated_at = models.DateTimeField(blank=True, null=True)
    created_at = models.DateTimeField(blank=True, null=True)
    updated_at = models.DateTimeField(blank=True, null=True)
    codb_id = models.IntegerField(blank=True, null=True)
    pm_lead_id = models.IntegerField(blank=True, null=True)
    version = models.CharField(max_length=20, blank=True, null=True)
    path_id = models.IntegerField(blank=True, null=True)
    branchpoint_type = models.CharField(max_length=255, blank=True, null=True)
    branchpoint_id = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'branches'
        verbose_name_plural = 'Branches'

class Projects(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=40, primary_key=True)
        status = models.CharField(max_length=255)
        platform = models.CharField(max_length=255)
        enabled = models.IntegerField()
        path = models.CharField(max_length=128, blank=True, null=True)
        tag_prefix = models.CharField(max_length=64, blank=True, null=True)
        created_at = models.DateTimeField(blank=True, null=True)
        updated_at = models.DateTimeField(blank=True, null=True)
        codb_id = models.IntegerField(blank=True, null=True)
        template = models.CharField(max_length=64, blank=True, null=True)
        image_path = models.CharField(max_length=128, blank=True, null=True)
        repository_id = models.IntegerField(blank=True, null=True)
        number_scheme = models.CharField(max_length=32)
        special_dir = models.CharField(max_length=32, blank=True, null=True)
        project_family_id = models.IntegerField()
        class Meta:
            managed = False
            db_table = 'projects'
            verbose_name_plural = 'projects'

class BranchesProjects(models.Model):
    # project_id = models.IntegerField()
    # branch_id = models.IntegerField()
    project = models.ForeignKey(Projects, on_delete=models.CASCADE)
    branch = models.ForeignKey(Branches, on_delete=models.CASCADE)

    class Meta:
        managed = False
        db_table = 'branches_projects'

我当前的原始查询是这样的

SELECT br.id, br.name, br.created_at, br.updated_at,
br.branchpoint_str, br.source
FROM branches as br
LEFT JOIN branches_projects as bp
ON br.id = bp.branch_id 
WHERE bp.project_id = %s AND source != 'other'
ORDER BY updated_at DESC

1 个答案:

答案 0 :(得分:0)

我终于搞定了......

在模型中,我使用了manytomany如下:

class Branches(models.Model):
name = models.CharField(max_length=128)
project = models.ManyToManyField(Projects,
    through='BranchesProjects',
    related_name='project')
branchpoint_str = models.CharField(max_length=255)

然后为了获得与原始sql相同的结果,我执行以下操作:

def get_sb(project_id):
    result = Branches.objects.filter(
        project=Projects.objects.get(id=project_id).id,
        ).exclude(source='other').order_by('-updated_at')
    print result.query
    return result