Django非常大的反向ForeignKey查询

时间:2015-05-26 08:57:30

标签: python django sqlite django-admin django-admin-filters

我正在使用Django admin来过滤其反向ForeignKey对象字段值上的对象。 App有一个ForeignKeyContact,我想在Django admin中按Contacts类别过滤Apps。问题是查询非常大,我收到超时错误。大约有300k个联系人对象和大约1M的应用程序。 Django admin每页有500个结果。添加了db索引和prefetch_related。我还应该做些什么来优化Django管理员?我正在使用sqlite db。

代码:

class App(models.Model):
    contact = models.ForeignKey('Contact', related_name='apps', null=True)
    category = models.TextField(blank=True, null=True, db_index=True)
    store = models.IntegerField(choices=STORE_TYPES, db_index=True)

    class Meta:
        index_together = [
            ['category', 'store'],
        ]

# admin:

class ContactAdmin(admin.ModelAdmin):
    list_filter = (
        AppCategory,
    )

    def queryset(self, request):
        return super(ContactAdmin, self).queryset(request).prefetch_related(
            'apps',
            'to_contact',
        )

# the main list_filter that is causing troubles:

class AppCategory(admin.SimpleListFilter):
    title = 'app category'
    parameter_name = 'app_category'

def lookups(self, request, modelAdmin):

    return [
        ('Action', 'Action'),
        ('Adventure', 'Adventure'),
        ('Arcade', 'Arcade'),
        ('Board', 'Board'),
        ('Books', 'Books'),
        ('Books & Reference', 'Books & Reference'),
        ('Business', 'Business'),
        ('Card', 'Card'),
        ('Casino', 'Casino',),
        ('Casual', 'Casual'),
        ('Catalogs', 'Catalogs'),
        ('Comics', 'Comics'),
        ('Communication', 'Communication'),
        ('Education', 'Education'),
        ('Educational', 'Educational'),
        ('Entertainment', 'Entertainment'),
        ('Family', 'Family'),
        ('Finance', 'Finance'),
        ('Food & Drink', 'Food & Drink'),
        ('Games', 'Games'),
        ('Health & Fitness', 'Health & Fitness'),
        ('Libraries & Demo', 'Libraries & Demo'),
        ('Lifestyle', 'Lifestyle'),
        ('Media & Video', 'Media & Video'),
        ('Medical', 'Medical'),
        ('Music', 'Music'),
        ('Music & Audio', 'Music & Audio'),
        ('Navigation', 'Navigation'),
        ('News', 'News'),
        ('News & Magazines', 'News & Magazines'),
        ('Personalization', 'Personalization'),
        ('Photo & Video', 'Photo & Video'),
        ('Photography', 'Photography'),
        ('Productivity', 'Productivity'),
        ('Puzzle', 'Puzzle'),
        ('Racing', 'Racing'),
        ('Reference', 'Reference'),
        ('Role Playing', 'Role Playing'),
        ('Shopping', 'Shopping'),
        ('Simulation', 'Simulation'),
        ('Social', 'Social'),
        ('Social Networking', 'Social Networking'),
        ('Sports', 'Sports'),
        ('Strategy', 'Strategy'),
        ('Tools', 'Tools'),
        ('Transportation', 'Transportation'),
        ('Travel', 'Travel'),
        ('Travel & Local', 'Travel & Local'),
        ('Trivia', 'Trivia'),
        ('Utilities', 'Utilities'),
        ('Weather', 'Weather'),
        ('Word', 'Word')
    ]

def queryset(self, request, queryset):
    if not self.value():
        return queryset
    else:
        qs = queryset.filter(
            apps__category=self.value()
        )
        return qs

1 个答案:

答案 0 :(得分:0)

我找到了答案。如果您正在过滤一个反向ForeignKey关系(在这种情况下为apps__category),一切正常。但我忘了提到我在Django管理页面的右侧组合了两个过滤器 - 另一个也是反向ForeignKey - apps__store。当您这样做时,会执行两个完全相同的INNER JOIN,这会导致服务器超时。当我单独使用这些过滤器时,一切正常。

请参阅:https://code.djangoproject.com/ticket/16554