I recently started evaluating Django for migrating our archaic web application written 10 years ago. I have been reading up Django documentation for the last few days, but haven't been able to figure out the best way to achieve a multi table database join in my case:
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)
(Note that model was generated by inspectdb and I'd prefer not to modify it at this point in time)
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 is designed to be minimal at this point to help focus on the real issue in (views/model).
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 %}
Problem:
Although I'm able to join Testmatrix and Testcase models, I am unable to generate an equivalent queryset by joining all of TestMatrix, TestCase, Status records on say productid='abc'
I tried the following:
1) Use select_related between Testmatrix and Testcases and Product tables and was able to access attributes across all three models (testmatrixid, productid, productname, testcaseid, testcasename). However I'm not sure how to extend this auto foreign key referencing to Status model. This would have been easier if all Foreign Keys were defined within Testmatrix itself. But Status has a Foreign Key to TestMatrix.
2) I tried using something like: entries = Status.objects.filter(testmatrixid__productid=pid). This again gave me a queryset as a result of joining Testmatrix and Status, but not Testcases.
Pardon any blaring mistakes or bloopers. This is my very first post!
So you need to access a related_object. It is very simple.
First, add related_name
here:
class Status(models.Model):
testmatrixid = models.ForeignKey(Testmatrix, db_column='TestMatrixId', related_name='statuses')
Now you can get all the statuses for desired Testmatrix like
test_matrix.statuses.all()
If you don't want to hit DB, when you access statuses
, don't forget to use select_related
.