【问题标题】:Django admin inline prefetch foreign relation of foreign relationDjango admin inline prefetch 对外关系的对外关系
【发布时间】:2017-05-01 14:55:58
【问题描述】:

我遇到了一个相当普遍的问题,即 django admin inline 会执行一大堆不必要的查询来填充下拉列表。有 4 个模型 - 当我查看用户时,我希望看到与该用户关联的 UserClientRoles,并显示 ClientRole 名称和客户端。当我只使用角色名称时,它会为每个 UserClientRole 查询一次(如果有 3 个分配,它会查询 3 次)。如果我包含客户端名称,它会为每个 UserClientRole 查询每个客户端名称一次。

我已经尝试过此处列出的解决方案 (Django admin inline: select_related),但没有骰子。它不会修改行为。我也尝试过覆盖 UserAdmin 类的 get_queryset 方法,但没有效果。我尝试过的任何方法都不会减少查询的数量。为了简洁,我删除了一些模型细节。

这是模型:

class User(models.Model):
    id = models.AutoField(primary_key=True)
    email = models.CharField(unique=True, max_length=200)


class Client(models.Model):
    id = models.AutoField(primary_key=True)
    client_name = models.CharField(unique=True, max_length=200)
    client_identifier = models.CharField(unique=True, max_length=200)


class ClientRole(models.Model):
    client_role_id = models.AutoField(primary_key=True)
    role_name = models.CharField(unique=True, max_length=200)
    client = models.ForeignKey(Client)

    def __unicode__(self):
        return self.role_name + self.client_id.client_name


class UserClientRole(models.Model):
    user_client_role_id = models.AutoField(primary_key=True)
    client_role = models.ForeignKey(ClientRole)
    user = models.ForeignKey(User)

这里是管理模型:

class UserClientRoleFormset(forms.BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        super(UserClientRoleFormset, self).__init__(*args, **kwargs)
        self.queryset = self.queryset.prefetch_related("client_role__client")


class UserClientRoleInline(admin.TabularInline):
    model = UserClientRole
    extra = 1
    formset = UserClientRoleFormset


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    inlines = (UserClientRoleInline,)

知道我错过了什么吗?

【问题讨论】:

  • 你试过我的答案了吗?
  • @e4c5 我没有设计表结构,也无法重写它。我也觉得我拥有的结构和你拥有的结构之间存在一些信息丢失,所以我不清楚这是向前迈出的一步
  • 远非如此,那里根本没有任何信息丢失。您现有的结构甚至没有使用内置的 django 多对多关系
  • @e4c5 嘿,您是否删除了您的答案?这个问题没有引起我的充分注意,我想我现在可以看到您的建议可能会有所帮助。希望你能恢复它,以便我们试一试。
  • 如果您不打算花时间研究这些答案,那么提出问题并期望人们花时间回答这些问题真的很糟糕

标签: python django django-admin


【解决方案1】:

试试:

self.queryset.select_related('client_role', 'client_role__client')

Django 并不总是最擅长决定选择哪些对象作为查询的一部分,即使您可能认为 django ORM 足够聪明,可以识别这一点,因为您正在遍历 @987654322 形式的关系@,不是。因此,确保在 select_relatedprefetch_related 中都指定过去对我有用。我会建议尝试一下!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 2012-07-22
    • 1970-01-01
    • 2015-04-03
    • 2016-07-29
    • 1970-01-01
    相关资源
    最近更新 更多