问题
I am using django-mssql 1.6.2 package with django 1.7 to get one or several records of tables from sql server 2008. When I call "get" or "filter" as follows, everything is fine but my server program is very slow. Consider the following tables:
class Contact(models.Model):
id = models.IntegerField(primary_key=True, unique=True, null=False)
address = models.CharField(max_length = 100)
phone = models.IntegerField(unique=True)
class Parent(models.Model):
id = models.IntegerField(primary_key=True, unique=True, null=False)
name = models.CharField(max_length = 50)
contact = models.OneToOneField(Contact)
class Student(models.Model):
id = models.IntegerField(primary_key=True, unique=True, null=False)
name = models.CharField(max_length = 50)
parent = models.ForeignKey(Parent)
Assume that we want to print a table in a template like:
Student name | Parent name | Parent phone number
John | Jack | 1111111
Susan | Jack | 1111111
Dan | Jack | 1111111
Jackie | Sara | 2222222
I use a code like:
query_results = list()
parents = Parent.objects.all()
for any_parent in parents:
students = Student.objects.filter(parent=any_parent)
for student in students:
element = TempObjectForStudent()
element.student_name = student.name
element.parent_name = any_parent.name
element.parent_phone = any_parent.contact.phone
query_results.append(element)
if students.__len__() == 0:
element = TempObjectForStudent()
element.student_name = 'without any active student'
element.parent_name = any_parent.name
element.parent_phone = any_parent.contact.phone
query_results.append(element)
class TempObjectForStudent():
student_name = None
parent_name = None
parent_phone = None
With a template like:
{% for row in query_results %}
<tr><td>{{ row.student_name }}</td><td>{{ row.parent_name }}</td><td>{{ row.parent_phone }}</td></tr>
As I mentioned before, the problem is the speed of running lots of queries in this method. How can I use join to deliver all of the table data in just one query?
回答1:
Ok, you made it a little bit too complicated.
There is no need for TempObjectForStudent. You can get the student instance without that. Simply add a related_name
to you Student
model's parent
field, so you can get reference to the Parent
object simply using dot notation.
Also please note that Django gives each model the id
field automaticaly. You can read more here and here. So there is no need to create that field explicitly in your models.
Regarding your question, I would do it like this:
# models.py
class Parent(models.Model):
name = models.CharField(max_length = 50)
contact = models.OneToOneField(Contact)
class Student(models.Model):
name = models.CharField(max_length = 50)
parent = models.ForeignKey(Parent, related_name='students')
# views.py
parents = Parent.objects.all()
# template.html
{% for parent in parents %}
<tr>
<td>
{% with parent.students.all as students %}
{% for student in students %}
{{ student.name }}
{% empty %}
'without any active student'
{% endfor %}
{% endwith %}
</td>
<td>
{{ parent.name }}
</td>
<td>
{{ parent.contact.phone }}
</td>
</tr>
{% endfor %}
Update:
I came across a select_related
QuerySet method. I think that this is what you've been searching for! It uses SQL JOIN
clause and includes all related object's fields in SELECT
statement. Read more here. I hope it helps!
来源:https://stackoverflow.com/questions/38678583/django-query-to-join-records-of-two-tables