Django模型查询的数据库访问机制

时间:2017-07-13 05:30:30

标签: mysql django python-2.7 django-models

class parent(models.Model):
    ap=models.CharField(max_length=10)
    user=models.CharField(max_length=10)

    class Meta:
        unique_together=(("ap","user"),)
        db_table='parent'


class child(models.Model):
    userkey=models.ForeignKey(parent,on_delete=models.CASCADE,db_column="ap")
    pn=models.CharField(max_length=10)
    st=models.CharField(max_length=10,default='Y')

    def get_ap(self):
        return self.ap.ap
    def get_pn(self):
        return self.pn
    class Meta:
        db_table="child"
        unique_together=(('userkey','pn'),)

我们说我有ap =" apkey"然后我可以访问所有的儿童模型对象" apkey"通过以下查询。

child_obj=child.objects.filter(userkey__ap="apkey")

这也可以在不使用外键关系的情况下完成,如下所示。

parent_obj=parent.objects.get(ap="apkey")
child_obj=child.objects.filter(userkey=parent_obj)

我必须知道的是,在两种方法中执行查询时发生了多少次数据库访问。 ?

在第二个中,我们知道它访问父表一次,然后访问子表一次。因此实际上发生了两次sql查询。

第一个怎么样?

2 个答案:

答案 0 :(得分:3)

Django查询集本质上是懒惰的。 see here in documentation。 因此,在执行第二段代码时,技术上只会发生只有一个数据库命中。

进一步阐述, 从文档中说明。

q = Entry.objects.filter(headline__startswith="What")
q = q.filter(pub_date__lte=datetime.date.today())
q = q.exclude(body_text__icontains="food")
print(q)

虽然这看起来像三个数据库命中,但事实上它只在最后一行(print(q))命中数据库一次。通常,在您“询问”它们之前,不会从数据库中获取QuerySet的结果。

对于向后关系see docs here,在运行settings.py时,会创建向后关系,并且它们在技术上也应该只进行一次命中。但我对此并不十分肯定,因为我在目前的文档中没有找到任何相关信息。

希望这会有所帮助。谢谢。

答案 1 :(得分:1)

正如@shivam所说,查询集本质上是懒惰的,只有当你要求它们时才会对它们进行评估。如果要查看正在执行的sql查询,可以使用connection。但是您只能看到当前进程的查询。查看正在执行的查询的最佳方法是使用django-debug-tool之类的工具。

from django.db import connection
parent_obj=parent.objects.get(ap="apkey")
child_obj=child.objects.filter(userkey=parent_obj)
print(len(connection.queries))

要查看查询,您可以使用查询集的query attribute。它包含要执行的查询 例如:

Mymodels.objects.all().query