Django-запрос на объединение записей двух таблиц
Я использую пакет django-mssql 1.6.2 с django 1.7, чтобы получить одну или несколько записей таблиц из sql server 2008. Когда я вызываю "get" или "filter" следующим образом, все в порядке, но моя серверная программа работает очень медленно. Рассмотрим следующие таблицы:
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)
Предположим, что мы хотим напечатать таблицу в шаблоне, например:
Student name | Parent name | Parent phone number
John | Jack | 1111111
Susan | Jack | 1111111
Dan | Jack | 1111111
Jackie | Sara | 2222222
Я использую код как:
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
С шаблоном вроде:
{% for row in query_results %}
<tr><td>{{ row.student_name }}</td><td>{{ row.parent_name }}</td><td>{{ row.parent_phone }}</td></tr>
Как я упоминал ранее, проблема заключается в скорости выполнения большого количества запросов в этом методе. Как я могу использовать объединение, чтобы доставить все данные таблицы в одном запросе?
1 ответ
Хорошо, ты сделал это слишком сложным.
Нет необходимости в TempObjectForStudent. Вы можете получить экземпляр студента без этого. Просто добавьте related_name
тебе Student
модели parent
поле, так что вы можете получить ссылку на Parent
объект просто с помощью точечной нотации.
Также обратите внимание, что Django дает каждой модели id
поле автоматически. Вы можете прочитать больше здесь и здесь. Поэтому нет необходимости явно создавать это поле в ваших моделях.
Что касается вашего вопроса, я бы сделал это так:
# 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 %}
Обновить:
Я наткнулся на select_related
Метод QuerySet. Я думаю, что это то, что вы искали! Он использует SQL JOIN
и включает в себя все поля связанного объекта в SELECT
заявление. Узнайте больше здесь. Я надеюсь, что это помогает!