Django三种方式使用外键加入

时间:2012-01-12 03:37:06

标签: django join models

我最近开始评估Django迁移我们10年前编写的古老Web应用程序。我最近几天一直在阅读Django文档,但是在我的案例中找不到实现多表数据库连接的最佳方法:

Model:

class Product(models.Model):
    productid = models.IntegerField(primary_key=True, db_column='ProductId') 
    productname = models.CharField(max_length=120, db_column='ProductName')

class Testcases(models.Model):
    testcaseid = models.IntegerField(primary_key=True, db_column='TestCaseId')
    testcasename = models.CharField(max_length=240, db_column='TestCaseName')

class Testmatrix(models.Model):
    testmatrixid = models.IntegerField(primary_key=True, db_column='TestMatrixId')
    productid = models.ForeignKey(Product, db_column='ProductId')
    testcaseid = models.ForeignKey(Testcases, db_column='TestCaseId')

class Status(models.Model):
    testmatrixid = models.ForeignKey(Testmatrix, db_column='TestMatrixId')
    title = models.CharField(max_length=240, db_column='Title', blank=True)

(注意,模型是由inspectdb生成的,我不想在此时修改它)

View:

from django.shortcuts import render_to_response
from mysite.testmatrix.models import Product, Testcases, Testmatrix, Status

def get_products(request):
    tm = list(Testmatrix.objects.filter(productid='abc'))
    return render_to_response('products.html', {'tm': tm})

模板目前设计为最小,以帮助关注(视图/模型)中的实际问题。

Template: (products.html)
{% extends "main.html" %}

{% block body %}
<table>
{% for tm in tm %}
    <tr>
            <td>{{ tm.testmatrixid }}</td>
    <td>{{ tm.testcaseid.testcasename }}</td>
    </tr>
{% endfor %}
</table>
{% endblock %}

问题:

虽然我能够加入Testmatrix和Testcase模型,但我无法通过加入所有TestMatrix,TestCase,状态记录来生成等效的查询集,比如说productid ='abc'

我尝试了以下内容:

1)在Testmatrix和Testcases与Product表之间使用select_related,并且能够访问所有三个模型的属性(testmatrixid,productid,productname,testcaseid,testcasename)。但是,我不确定如何扩展此自动外键引用状态模型。如果在Testmatrix本身中定义了所有外键,这将更容易。但是Status有一个TestMatrix的外键。

2)我尝试使用类似:entries = Status.objects.filter(testmatrixid__productid = pid)。这再次给了我一个查询集,作为加入Testmatrix和Status的结果,而不是Testcases。

原谅任何明显的错误或蠢货。这是我的第一篇文章!

2 个答案:

答案 0 :(得分:2)

因此您需要访问related_object。这很简单。

首先,在此处添加related_name

class Status(models.Model):
    testmatrixid = models.ForeignKey(Testmatrix, db_column='TestMatrixId', related_name='statuses')

现在您可以获得所需的Testmatrix的所有状态,如

test_matrix.statuses.all()

如果您不想点击数据库,当您访问statuses时,请不要忘记使用select_related

答案 1 :(得分:0)

如果没有任何特定的错误消息,很难诊断出错误的原因。但是,在您的示例中,在views.get_products中:tm = list(Testmatrix.objects.filter(productid='abc'))将不起作用,因为'abc'是一个字符串,您的productid实际上是一个Product对象(不只是一个整数,即使该字段是整数外键到参考表的pk);你可以做tm = list(Testmatrix.objects.filter(productid=Product.objects.get(product_name='abc')),假设'abc'是产品记录的产品名称。当您将字段设置为models.ForeignKey(...)时,您将该引用记录作为对象而不是id。

除此之外,没有什么明显的,你的模板看起来很稳固,你的模型看起来很好。我建议创建一些测试用例以查看错误所在:Django Testing;此外,this也是了解使用Django进行TDD和单元测试的好教程。使用单元测试,您可以验证应用程序的每个步骤,并在保证的情况下进行将来的更新。