在Django的管理面板查询中删除联接

时间:2014-03-20 02:48:25

标签: django django-models django-admin django-queryset django-orm

我有一些奇怪的问题,这是由于Django管理面板想要构建一个查询来显示项目列表并忽略我的提示。它发出包含JOIN的查询,即使我希望它避免它们以便为底层数据库后端节省大量工作。

基本上考虑3种型号:

  • Book
  • BookTemplate
  • Author

Book有一些重列(包含整本书),而BookTemplate有类似的内容(例如,它包含布局的定义,然后填充内容并创建Book )。

结构类似于:

class Author(models.Model):
    uuid = django_extensions.db.fields.UUIDField(primary_key=True)
    created = django_extensions.db.fields.CreationDateTimeField(db_index=True)
    name = models.CharField(max_length=255)

class BookTemplate(models.Model):
    uuid = django_extensions.db.fields.UUIDField(primary_key=True)
    created = django_extensions.db.fields.CreationDateTimeField(db_index=True)
    content = models.TextField()

class Book(models.Model):
    uuid = django_extensions.db.fields.UUIDField(primary_key=True)
    created = django_extensions.db.fields.CreationDateTimeField(db_index=True)
    content = models.TextField()
    template = models.ForeignKey('BookTemplate')
    author = models.ForeignKey('Author')

当访问Django管理页面列出Book个实例时,Django会发出如下数据库调用,这一切都很好(如果不是这样的话):

SELECT
    "myapp_book"."uuid", "myapp_book"."content", (...)
INNER JOIN
    "myapp_booktemplate"
    ON ("myapp_book"."template_id" = "myapp_booktemplate"."uuid")
INNER JOIN
    "myapp_author"
    ON ("myapp_book"."author_id" = "myapp_author"."uuid")
ORDER BY
    "myapp_book"."created" DESC,
    "myapp_book"."uuid" DESC;

这个查询的问题在于,由于MySQL的处理方式,它会导致创建巨大的临时表。我想摆脱JOIN s。

然而,用这样的东西覆盖ModelAdmin.queryset()无济于事:

class BookModelAdmin(ModelAdmin):
    def queryset(request):
        return super(BookModelAdmin, self).queryset(request).prefetch_related(
            'author', 'template',
        )

选中后,家长的.queryset()方法会返回尚未包含任何需要QuerySet的条件的JOIN

我想:

  • 强制Django页面列出Book个实例,以便在没有JOIN的情况下使用查询(或查询)执行此操作,
  • 删除uuid的默认排序(这很愚蠢,因为此值完全是随机的),

我错过了什么?有没有一些标准的方法呢?我想节省编写管理面板自定义实现的时间,我相信其他人也会遇到类似的问题。

0 个答案:

没有答案