python - Django 查询优化 - 使用 Itertools

标签 python mysql django django-models

我有一个教育网站,根据年级水平提供类(class)。

  1. GradeLevel 表存储所有可能的等级水平。然后我有 LessonCategories 和 LessonCurriculum 表。

  2. GradeLevel 表与 curriculum 和 categories 表建立了反向关系。

  3. 我遍历 GradeLevel 表中的每个年级(8 个年级),并沿途获取相应的类(class)和类别。

  4. 完成后,我将所有收集的类(class)和类别填充到一个列表中,并将其传递到我的模板。

现在,问题是 Django 至少对每个查询求值两次。一次用于初始请求,第二次用于我将其放入列表时。 (我正在使用 itertools 来链接结果。Itertools 导致查询再次运行。)这产生了不利影响,使我的服务器速度减慢到爬行速度。

我的问题是,是否有人可以查看我的模型和查询,并就更好的查询方式提出建议,以避免和/或缓解这一主要性能瓶颈。

年级模型:

class GradeLevel(models.Model):
    title = models.CharField('Grade',max_length=10, null=True, blank=True, db_index=True)
    fullname = models.CharField('Description',max_length=100, null=True, blank=True, db_index=True)

类(class)类别模型:

class LessonCategory(models.Model):
    title = models.CharField(max_length=255, null=True, blank=True, db_index=True)
    ...
    gradelevel = models.ManyToManyField(GradeLevel, related_name='grade_cats', null=True, blank=True)

类(class):

class LessonCurriculum(models.Model):         
    title = models.CharField(max_length=255, null=True, blank=True, db_index=True)
    ...
    gradelevel = models.ManyToManyField(GradeLevel, related_name='grade_curriculum', null=True, blank=True)

我的看法:

from itertools import chain
from operator import attrgetter

def my_view(request):
    grade_pk =  GradeLevel.objects.prefetch_related().get(title='pre-k')
    grade_pk_categories = grade_pk.grade_cats.filter(active=True,featured=True)
    grade_pk_galleries = grade_pk.grade_curriculum.filter(active=True,featured=True)

    grade_k =  GradeLevel.objects.prefetch_related().get(title='k')
    grade_k_categories = grade_k.grade_cats.filter(active=True,featured=True)
    grade_k_galleries = grade_k.grade_curriculum.filter(active=True,featured=True)

    grade_1 =  GradeLevel.objects.prefetch_related().get(title='1')
    grade_1_categories = grade_1.grade_cats.filter(active=True,featured=True)
    grade_1_galleries = grade_1.grade_curriculum.filter(active=True,featured=True)

    grade_2 =  GradeLevel.objects.prefetch_related().get(title='2')
    grade_2_categories = grade_2.grade_cats.filter(active=True,featured=True)
    grade_2_galleries = grade_2.grade_curriculum.filter(active=True,featured=True)

    grade_3 =  GradeLevel.objects.prefetch_related().get(title='3')
    grade_3_categories = grade_3.grade_cats.filter(active=True,featured=True)
    grade_3_galleries = grade_3.grade_curriculum.filter(active=True,featured=True)

    grade_4 =  GradeLevel.objects.prefetch_related().get(title='4')
    grade_4_categories = grade_4.grade_cats.filter(active=True,featured=True)
    grade_4_galleries = grade_4.grade_curriculum.filter(active=True,featured=True)

    grade_5 =  GradeLevel.objects.prefetch_related().get(title='5')
    grade_5_categories = grade_5.grade_cats.filter(active=True,featured=True)
    grade_5_galleries = grade_5.grade_curriculum.filter(active=True,featured=True)

    grade_6 =  GradeLevel.objects.prefetch_related().get(title='6')
    grade_6_categories = grade_6.grade_cats.filter(active=True,featured=True)
    grade_6_galleries = grade_6.grade_curriculum.filter(active=True,featured=True)

    grade_7 =  GradeLevel.objects.prefetch_related().get(title='7')
    grade_7_categories = grade_7.grade_cats.filter(active=True,featured=True)
    grade_7_galleries = grade_7.grade_curriculum.filter(active=True,featured=True)

    grade_8 =  GradeLevel.objects.prefetch_related().get(title='8')
    grade_8_categories = grade_8.grade_curriculum.filter(active=True,featured=True)
    grade_8_galleries = grade_8.grade_curriculum.filter(active=True,featured=True)

    gallery_list = list(set(sorted(chain(grade_pk_categories,grade_pk_galleries,grade_k_categories,grade_k_galleries,grade_1_categories,grade_1_galleries,grade_2_categories,grade_2_galleries,grade_3_categories,grade_3_galleries,grade_4_categories,grade_4_galleries,grade_5_categories,grade_5_galleries,grade_6_categories,grade_6_galleries,grade_7_categories,grade_7_galleries,grade_8_categories,grade_8_galleries), key=attrgetter('display_order'))))

最佳答案

我会更进一步优化@NathanVillaescusa 的回答

grade_titles = ['pre-k', 'k', '1', '2', '3', '4', '5', '6', '7', '8']

# Turn list into list of Q items
queries = [models.Q(title=grade_title) for grade_title in grade_titles]

# Take one item of the list
query = queries.pop()

# OR the Q objects with the ones remaining in the list
for item in queries:
    query |= item

grades = GradeLevel.objects.prefetch_related().filter(query)
# grades should have everything you need and operation is more CPU
# and less DB bound now

关于python - Django 查询优化 - 使用 Itertools,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13127526/

相关文章:

python - 在 python 中使用 for 循环将 skimage.filters.threshold_otsu() 应用于图像/数组中的段列表时遇到问题

mysql - 在此查询中,如何在 GROUP BY 之前执行 SELECT?

json - 为什么我的 Django Rest Framework 端点的右括号松动?

python - 为什么在 python 中给 str func 一个 unicode 字符串会抛出异常?

python - 从 NLP 中的名词相提取名词

python - 操作系统错误: [Errno 22] Invalid argument (Paramiko)

php - 如何通过打开购物车中的 SEO 友好 URL 测试

PHP上传图片到数据库

python - Django 中将foreignkey 放在哪里?

python - 迭代并设置类属性 - Python Django