# Access prefetch\_related objects

**URL:** <https://forum.djangoproject.com/t/access-prefetch-related-objects/19173>\
**Category:** Using the ORM\
**Created:** [February 28, 2023, 8:58pm UTC](https://forum.djangoproject.com/t/access-prefetch-related-objects/19173 "2023-02-28T20:58:28Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![spinozagl](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/spinozagl/32/12450_2.png) [@spinozagl](https://forum.djangoproject.com/u/spinozagl)\
**Post date:** [February 28, 2023, 8:58pm UTC](https://forum.djangoproject.com/t/access-prefetch-related-objects/19173/1 "2023-02-28T20:58:28Z")

</div>

```auto
latest_update = BillHistory.objects.filter(
            bill=OuterRef('id')).order_by('-occurred_datetime')
        user_bills = Bill.objects.only(
            "bill_number", "short_title").filter(session='2023-2024').filter(
                Q(users__archived=False)
                & Q(users__user=user)).annotate(
                    priority=F('users __billuserpriority__ priority'),
                    position=F('users __billuserposition__ position'),
                    latest_update_on=Max('histories__occurred_datetime'),
                    committee_names=Subquery(
                        latest_update.values('committee_names__name')[:1]),
                    latest_update_status=Subquery(
                        latest_update.values('status')[:1])).prefetch_related(
                            'users __clients__ client',
                            'users __pillars__ pillar').order_by(
                                Func(F('bill_number'), function='alphanum'))

```

prefetch\_related works wonders here. What is the more performant query to access the prefetched objects? At the moment, I am accessing a client object like so in the template: bill.users.all → users.clients.all → client. Although I am able to filter first by user and then by clients for that user, this is resulting in duplicate and similar queries. Thank you.

---

<div class="post-metadata">

**Author:** ![jnns](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jnns/32/950_2.png) [@jnns](https://forum.djangoproject.com/u/jnns)\
**Post date:** [March 1, 2023, 1:03pm UTC](https://forum.djangoproject.com/t/access-prefetch-related-objects/19173/2 "2023-03-01T13:03:03Z")

</div>

Which query is duplicated exactly?

Did you try the [Prefetch](https://docs.djangoproject.com/en/4.1/ref/models/querysets/#django.db.models.Prefetch) object with its `to_attr=` option to specify an attribute on the QuerySet model to store the prefetched object in a list in?

If you use `Prefetch(..., to_attr="clients")`, you can access them via `bill.clients` in your template.

```python
# This is your code snippet formatted with Black (https://black.readthedocs.io)
# This way it's easier for others to see what your queryset actually does.

latest_update = BillHistory.objects.filter(bill=OuterRef("id")).order_by(
    "-occurred_datetime"
)

user_bills = (
    Bill.objects.only("bill_number", "short_title")
    .filter(session="2023-2024")
    .filter(Q(users__archived=False) & Q(users__user=user))
    .annotate(
        priority=F("users __billuserpriority__ priority"),
        position=F("users __billuserposition__ position"),
        latest_update_on=Max("histories__occurred_datetime"),
        committee_names=Subquery(latest_update.values("committee_names__name")[:1]),
        latest_update_status=Subquery(latest_update.values("status")[:1]),
    )
    .prefetch_related("users __clients__ client", "users __pillars__ pillar")
    .order_by(Func(F("bill_number"), function="alphanum"))
)

```

---

<div class="post-metadata">

**Author:** ![spinozagl](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/spinozagl/32/12450_2.png) [@spinozagl](https://forum.djangoproject.com/u/spinozagl)\
**Post date:** [March 1, 2023, 4:47pm UTC](https://forum.djangoproject.com/t/access-prefetch-related-objects/19173/3 "2023-03-01T16:47:48Z")

</div>

Thank you for your response.

I use yapf for formatting. Black works well too.

I have tried using Prefetch with the to\_attr attribute set.

```auto
.prefetch_related(Prefetch("users__clients", queryset=BillUserClient.objects.filter(billuser=user), to_attr="bill_clients"))

```

I’d like to access clients attached to a bill by an authenticated user, in my template passing a Bill instance to the context. I’d like to do this without looping through all users and all clients. I am trying to work out why I can’t seem to use bill.bill\_clients to access the clients attached to the bill by a particular authenticated user using prefetch\_related with Prefetch.

There are through-tables between Bill, User, and Client, without any explicit many-to-many field set in the Bill model or the Client model (see below)

```auto
class BillUser(TimestampedModel):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             related_name='bills',
                             on_delete=models.RESTRICT)
    bill = models.ForeignKey(Bill,
                             related_name='users',
                             on_delete=models.RESTRICT)

    archived = models.BooleanField("Archived", default=False)

    class Meta:
        # unique_together = ('user', 'bill')
        constraints = [
            models.UniqueConstraint(fields=['user', 'bill'],
                                    name='bill_user_unique')
        ]
        indexes = [
            models.Index(fields=['user', 'bill'], name='bill_user_idx'),
            models.Index(fields=['bill'], name='bill_user_bill_idx'),
            models.Index(fields=['user'], name='bill_user_user_idx'),
            models.Index(fields=['archived'], name='bill_user_archived_idx'),
        ]

    def __str__ (self):
        return f"{self.user} - {self.bill} - archived: {self.archived}"

```

```auto
class BillUserClient(TimestampedModel):
    """
    Many-to-Many through table for BillUser and Client Models
    """
    billuser = models.ForeignKey(BillUser,
                                 related_name='clients',
                                 on_delete=models.RESTRICT)
    client = models.ForeignKey(KslegbtrClient,
                               related_name='billusers',
                               on_delete=models.RESTRICT)

    class Meta:
        # unique_together = ('billuser', 'client')
        constraints = [
            models.UniqueConstraint(fields=['billuser', 'client'],
                                    name='billuser_client_unique')
        ]
        ordering = ['client']

    def __str__ (self):
        return f"{self.billuser} - {self.client.short_name}"

```
