Django查询在循环中有效

时间:2015-01-21 10:37:08

标签: python django django-models

我在遗留数据库上创建了一个功能,这是正常的。但是表现有问题。通过分析,我注意到循环中的查询对性能有影响。请参阅下面的代码,了解如何开发功能,这只是代码的一小部分。

class Article(ReadOnlyModel, models.Model):
  article_id = models.IntegerField(primary_key=True,db_column=u'lArticle_id')
  description = models.TextField(db_column=u'cDescription')
  article_number = models.TextField(db_column=u'cArticlenr', blank=True)

class ArticleImage(ReadOnlyModel, models.Model):
    article_image_id = models.IntegerField(primary_key=True, db_column='intArticleImageId')
    article = models.ForeignKey('Article', db_column=u'intArticleId', related_name='images')
    image_link = models.TextField(db_column='chvImageLink', blank=True)
    image_kind = models.SmallIntegerField(null=True, db_column='inyImageKind', blank=True)
    insert_date = models.DateTimeField(null=True, db_column='dtmInsertDate', blank=True)

articles = Article.objects.all()

result = []
for article in articles:
    # Get image from article
    try:
        image = article.images.filter(image_kind=1).latest('insert_date').image_link
    except ArticleImage.DoesNotExist:
        image = ""

    soap_fabric = soap.SFabric(
        id=article.article_id,
        name=article.description,
        articleNumber=article.article_number,
        image=image
    result.append(soap_fabric)

    return result

如何改进这部分代码?

2 个答案:

答案 0 :(得分:1)

如果图像的ID随着时间的推移而增加,您可以尝试这样的方法来获取一个查询和子查询中的所有最新图像(而不是对每篇文章进行额外的查询):

   from django.db.models import Max

   image_ids = Article.objects.annotate(
        latest_image_id=Max('images__article_image_id')
   ).values_list('latest_image_id', flat=True)   

   latest_images = ArticleImage.objects.filter(
       pk__in=image_ids
   ).select_related('article')

答案 1 :(得分:0)

您可以将查询数量减少到两个:

  1. 将最新的图片链接加载到字典中;
  2. 在文章循环中使用此dict。
  3. 以下是示例:

    images_qs = ArticleImage.objects.filter(image_kind=1) \
                            .values('article', 'image_link', 'insert_date') \
                            .order_by('-insert_date')
    images = {}
    for img in images_qs:
        images.setdefault(img['article'], img['image_link'])
    
    result = [soap.SFabric(id=article.article_id,
                           name=article.description,
                           articleNumber=article.article_number,
                           image=images.get(article.article_id, ''))
              for article in Article.objects.all()]