简体   繁体   中英

Model Manager for non-empty records that includes objects from another manager

I have two models with managers: Category and Project.

class PopulatedCategoriesManager(models.Manager):
    def get_query_set(self):
        return super(PopulatedCategoriesManager, self) \
            .get_query_set() \
            .filter(projects__is_published=True).distinct()

class Category(models.Model):
    title = models.CharField(max_length=50)

    class Meta(Orderable.Meta):
        verbose_name_plural = 'Categories'

    objects = models.Manager()
    populated = PopulatedCategoriesManager()

class PublishedProjectsManager(models.Manager):
    def get_query_set(self):
        return super(PublishedProjectsManager, self) \
            .get_query_set().filter(is_published=True)

class Project(models.Model):
    title = models.CharField(max_length=50)
    category = models.ForeignKey(Category, related_name='projects')
    #other fields

    objects = models.Manager()
    published = PublishedProjectsManager()

The PopulatedCategoriesManager works as expected, returning only the Categories that have Projects that are published, but my problem is at the template level. I'm having trouble accessing only the published projects.

In the loop, the category instance doesn't know how to access only the published projects, so I'm curious as to what the most efficient way of getting to those objects is?

I'd love to be able to write...

{% for category in categories %}
    {% for project in category.published_projects.all %}

    {% endfor %}
{% endfor %}

...without making a database call for each category. Can someone please give me some pointers? I can write some raw SQL to do this, and I have some ideas from another Stack Overflow post to make this work, but I'd like to solve this at the model level.

I think your best bet is probably to just query all published_projects, ordered by category_id, then regroup them in the template.

projects = Project.published.all().order_by('category_id')

...

{% regroup projects by category_id as project_categories %}

{% for category in project_categories %}
    {% for project in category.list %}
        {{ project.title }}
    {% endfor %}
{% endfor %}

You don't show whether you need details of the category as well as just using it as a grouper, but if you do you can add select_related() to the original query.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM