0

我需要轻松控制在哪个站点上显示哪些产品,并且由于产品很多,我还想通过类别、生产商和标签设置产品站点。因此,如果产品 OR(其类别及其生产者及其一个标签)链接到该站点,我会在该站点上显示该产品。我最终得到的代码如下(简化):

from django.db.models import Model, ManyToManyField, ForeignKey, BooleanField

class Site(Model):
    enabled = BooleanField()

class Producer(Model):
    sites = ManyToManyField(Site)

class Category(Model):
    sites = ManyToManyField(Site)

class Tag(Model):
    sites = ManyToManyField(Site)

class Product(Model):
    producer = ForeignKey(Producer)
    category = ForeignKey(Category)
    tags     = ManyToManyField(Tag)
    sites    = ManyToManyField(Site)

    def get_site_ids(self):
        if self.sites.exists():
            return list(self.sites.values_list('id', flat=True))
        else:
            p = list(self.producer.sites.values_list('id', flat=True))
            c = list(self.category.sites.values_list('id', flat=True))
            t = sum([list(tag.sites.values_list('id', flat=True)) for tag in self.tags.all()], [])
            ids = set.intersection(set(p), set(c), set(t))
            return ids

我的问题是如何优化get_sites方法?是否可以加入一些查询?


更新:我只对将由搜索引擎索引和存储的站点 ID 感兴趣。

4

2 回答 2

1

select_related是的,您可以使用和/或减少 Django 中的查询数量prefetch_related

但是,select_related仅适用于外键和一对一关系。由于您的 Product 模型中有 ManyToMany,因此您应该使用它prefetch_related来减少 Product.get_sites() 中的查询。

于 2012-10-01T17:13:23.240 回答
1

You should try and do everything you want to do on the database level if possible. Something like this should get you started.

from django.db.models import Sum
self.objects.select_related("producer__sites",
                            "category__sites",
                            "tags__sites",
                            "sites").annotate(tag_count=Sum("tags__sites__id"))

select_related returns the Product model with the producer, category, tags and sites references filled. This also includes the sites reference in producer, category and tags. This make Django do less queries to the database.

annotate adds an attribute to the returned Model instance named tag_count that has the Sum of tags_sites_id in it.

The Django QuerySet Reference might be a good help because I don't know the exact nature of what you want to have returned.

于 2012-10-01T16:51:48.613 回答