从多个类别(多对多rel)中检索多个对象,以更多的djangoish方式

时间:2012-01-15 10:47:39

标签: django orm django-orm

我正在开发一个时事通讯系统。在这个系统中有Newslettercategories和Newsletterabos(说订阅),它们有很多关系。 考虑这两个模型:

class NewsletterCategory(models.Model):
    title = models.CharField(max_length=255, unique=True)
    slug = models.SlugField(max_length=255, unique=True)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering=['title']

    def __unicode__(self):
        return self.title


class NewsletterAbo(models.Model):
    abo_id = models.CharField(max_length=255, unique=True)
    first_name = models.CharField(max_length=255, unique=False)
    last_name = models.CharField(max_length=255, unique=False)
    email = models.EmailField(max_length=75, unique=False)
    is_active = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    categories = models.ManyToManyField(NewsletterCategory, blank=True)

    class Meta:
        ordering=['last_name']

    def __unicode__(self):
        return (self.last_name + ', ' +self.first_name)

现在想象一下,我想向多个NewsletterCategories发送一份时事通讯,而不会多次向一个电子邮件发送简讯。如果一个NewsletterAbo在多个NewsletterCategories中,则可能会发生这种情况。 到目前为止,我收集了Abos,我想发送邮件与此类似(避免重复):

# get all NewsletterCategories that are active, 
categories = NewsletterCategory.objects.filter(is_active=True)
# initialize empty list for storing NewsletterAbos
abolist = []
# loop through retrieved NewsLetterCategories
for cat in categories:
    # get NewsletterAbos that are related to a NewsletterCategory
    abos = cat.newsletterabo_set.filter(is_active=True)
    # add retrieved NewsletterAbos to list
    abolist += abos
# removing duplicate entries
abolist = set(abolist)

# ... do something else then like sending out newsletter to abolist subscriptions

Abolist现在是一个没有重复的abolist项目列表。 我的问题是:使用ORM是否有更多的“django-ish”方式。

感谢任何帮助。

更新 在lazerscience答案的帮助下,我想出了以下适合我需要的代码:

qs=NewsletterAbo.objects.filter(categories__is_active=True, 
                                categories__id__in=[1,2,3,4], 
                                is_active=True).distinct()

这行代码检索我需要的所有NewsletterAbos。新的qs存储列表(这是一个诚实的查询集)我之前存储在abolist中的abo项目。

谢谢:)!

1 个答案:

答案 0 :(得分:1)

如果您只需要发送简报的电子邮件,您可以这样做:

qs = NewsletterAbo.objects.filter(categories_set__is_active=True)
qs = qs.values_list('email', flat=True).distinct()

这将为您提供一个唯一的电子邮件地址列表,同时只访问数据库一次。 有关distinct()values() / values_list()的更多信息,请查看django文档。