【问题标题】:Django query to join records of two tablesDjango查询连接两个表的记录
【发布时间】:2016-12-05 08:06:21
【问题描述】:

我正在使用 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>

正如我之前提到的,问题在于在这种方法中运行大量查询的速度。如何使用 join 在一个查询中传递所有表数据?

【问题讨论】:

    标签: django python-3.x django-models django-queryset django-mssql


    【解决方案1】:

    好吧,你说得有点太复杂了。

    不需要 TempObjectForStudent。您可以在没有它的情况下获取学生实例。只需在Student 模型的parent 字段中添加一个related_name,这样您就可以使用点符号来引用Parent 对象。

    另外请注意,Django 会自动为每个模型提供id 字段。您可以阅读更多 herehere。因此,无需在模型中显式创建该字段。

    关于你的问题,我会这样做:

    # 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 语句中包含所有相关对象的字段。阅读更多here。希望对你有帮助!

    【讨论】:

    • 谢谢,但我认为这不会真正影响性能。能否请您也提供一个连接表格的解决方案?
    • 您认为不影响性能的原因是什么?我不使用任何其他查询,例如代码中使用的过滤,这会影响性能。创建 TempObjectForStudent 的新实例,为其分配属性 - 这是我在提议的解决方案中不做的另一件事,它可能会影响您的性能。我不知道您所说的“连接表”是什么意思?你想达到什么目的?
    • 您提到问题是在代码中运行查询的速度,但是,就我个人而言,我不认为将数据加入一个表(您需要使用另一个查询来做到这一点)会帮助您加快速度。我不是专家,所以我可能错了,但这只是我个人的看法。
    • 是的,我可以使用 select_related 和 prefetch_related @an0o0nym 来提高性能
    猜你喜欢
    • 2023-03-12
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    相关资源
    最近更新 更多