# Reading Extra Fields in a ManyToMany ("through") Table

**URL:** <https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676>\
**Category:** Using the ORM\
**Created:** [November 25, 2021, 10:20pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676 "2021-11-25T22:20:18Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![LJE2](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lje2/32/6455_2.png) [@LJE2](https://forum.djangoproject.com/u/LJE2)\
**Post date:** [November 25, 2021, 10:20pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/1 "2021-11-25T22:20:18Z")

</div>

I’m relatively newish to Django, working on a little project to practise what I’m learning.

I have a table with a ManyToManyField that specifies a “through table” so that I can add a bit more information to the many-to-many relationship. All works fine and I’ve got some test data, no problems for the most part.

I’m stuck now though trying to work out how to read a field from the link in a view function along the following lines – edited for brevity and clarity…

```auto
def display_my_thing(request, ref_ident):
    qryset = Catalogue.objects.filter(Q(something...) | Q(more...) | Q(otherthing)).select_related().distinct()
    my_obj = qryset.first() # For simplicity's sake here.

    caption_html = my_obj.caption # Ordinary field is fine.
    related_title = my_obj.entry.title # Regular related field is fine.

    extra_info = my_obj.manytomanyTable.extra_field_name # <-- No idea how to do this.

    # I'll give an example below based on the Django docs to make things easier.

    pass # Etc....

```

So that we can talk about a concrete example without pasting a tonne of code, let’s just use the example in the Django docs here – [Models | Django documentation | Django](https://docs.djangoproject.com/en/3.2/topics/db/models/#intermediary-manytomany) (The Django docs are **fabulous** btw. A huge resource!)

Let’s suppose I get a Group object like this:  
`g = Group.objects.filter(...something...).select_related().dictinct().first()`

Now, I can inspect g.name, or g.members\_\_person (or something like that, I forget), but what I want to do in my view function is to pull out the “invite\_reason”. I’m trying things like the following, but none of them work:  
`why_invited = g.membership__invite_reason`

I can inspect a lot of things with a “manage.py shell” but that’s not solved it for me here so far!

I’m hoping I’ve included a decent enough description to answer what is probably a simple question once you know 🙂

Thanks in advance,  
James.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [November 25, 2021, 10:40pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/2 "2021-11-25T22:40:03Z")

</div>

Actually, rather than trying to mix examples from the docs with what you’re trying to do, it’s likely going to be easier if you post your models here.

In general, you retrieve any attribute of any table using the “dot notations”. (The underscore notation only really applies as the parameter to a function such as filter.)

Keep in mind that a ManyToMany relationship means that you can have multiple references to the same tables at both ends. So to access the extra fields, you first need to identify _which_ row you’re interested in, requiring you to filter by both ends of the relationship.

---

<div class="post-metadata">

**Author:** ![LJE2](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lje2/32/6455_2.png) [@LJE2](https://forum.djangoproject.com/u/LJE2)\
**Post date:** [November 25, 2021, 10:56pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/3 "2021-11-25T22:56:25Z")

</div>

I thought that might be confusing – I started trying to post my example, but would end up with pages of irrelevant noise, I decided the example from the docs made a LOT more sense.

And yes, forgot to use the dot notation. I should have written ` why_invited = g.membership.invite_reason` or some such.

I know SQL pretty well, and I know my filter gets what I want, and the first() grabs the row I’m interested in, which will include a single Many-to-Many record, too, because of how I filter it.

The crux of my question is that (as the docs say), select\_related() works for OneToOne and ForeignKey – it says nothing about the ManyToMany case – which, I think, is why I can’t find the way to refer to the “extra fields” in my “through table” for the single row I’m trying to retrieve. Do I need to change the earlier line to explicitly pull those columns into the result?

Je.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [November 25, 2021, 11:00pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/4 "2021-11-25T23:00:41Z")

</div>

Ok, we can work with the docs example. Posted here for clarity:

```auto
from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__ (self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__ (self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

```

Using this as the base, what is your question?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [November 25, 2021, 11:05pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/5 "2021-11-25T23:05:16Z")

</div>

> [@LJE2](#):
>
> The crux of my question is that (as the docs say), select\_related() works for OneToOne and ForeignKey – it says nothing about the ManyToMany case

One item I will clarify - [select\_related](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#select-related) and [prefetch\_related](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#prefetch-related) have **nothing** to do with _access_ to data. They are performance-enhancements _only_. They are never _needed_ for _any_ purpose.

---

<div class="post-metadata">

**Author:** ![LJE2](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lje2/32/6455_2.png) [@LJE2](https://forum.djangoproject.com/u/LJE2)\
**Post date:** [November 25, 2021, 11:28pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/6 "2021-11-25T23:28:40Z")

</div>

Oh yes, I forgot I think I read something about them being for performance, thanks for the reminder.

So, yes, my question…

Suppose I have something like:

`g = Group.objects.filter(...something...).dictinct().first()`

where that “…something…” is some criteria that both (a) give me one Group object and (b) only one relevant many-to-many row from the Membership model/table. I’m familiar with doing that in SQL where I’d have some outer joins to perform selection on my Group table and the linked Membership table to produce a single row in which I have columns from Group and at least a column or two from Membership.

Using Django, I can refer to `g.name` easily and obviously, but anything I do to try and extract the “invite\_reason” column from my single-record result just produces an error.

I can get everything I need from everywhere else in all cases – it’s purely a problem when I try to fetch extra field data from the “through table”.

The closest thing in the aforementioned docs ([Models | Django documentation | Django](https://docs.djangoproject.com/en/3.2/topics/db/models/#intermediary-manytomany)) is where it says the following:

> If you need to access a membership’s information you may do so by directly querying the Membership model:
> 
> ```auto
> >>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
> >>> ringos_membership.invite_reason
> 'Needed a new drummer.'
> 
> ```

What I’m trying to do is to get that “invite\_reason” for the single row I retrieved in my initial query, which will have filters/criteria that ensure only one many-to-many row is matched for the retrieved Group.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [November 25, 2021, 11:36pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/7 "2021-11-25T23:36:19Z")

</div>

Ok, so the issue is that while _you_ might “know” that there’s only one matching many-to-many row, there’s no “proof” or “assurance” **at the database layer** that that condition holds.

Any time you have a single Group object, you must **always** account for the **possibility** that there’s more than one Membership associated with it.

To that end, if `group` is an instance of `Group`, then the set of `Membership` related to `group` is `group.membership_set`. (See [Related objects reference | Django documentation | Django](https://docs.djangoproject.com/en/3.2/ref/models/relations/)).

At _that_ point, you then need to identify _which_ member of that set to access. If you know that there is only one, so that you are not relying upon an indeterminate sort order, your reference to that singular `Membership` object is `group.membership_set.first()`. Therefore, the reference to the `invite_reason` member is `group.membership_set.first().invite_reason`.

---

<div class="post-metadata">

**Author:** ![LJE2](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lje2/32/6455_2.png) [@LJE2](https://forum.djangoproject.com/u/LJE2)\
**Post date:** [November 25, 2021, 11:38pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/8 "2021-11-25T23:38:04Z")

</div>

Aha! At a quick glance, I think I see it now – I need to use first() twice, once on my result and then again on the membership set… looks promising.

I’ll go try it out and let you know how I get on! 👍

---

<div class="post-metadata">

**Author:** ![LJE2](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/lje2/32/6455_2.png) [@LJE2](https://forum.djangoproject.com/u/LJE2)\
**Post date:** [November 25, 2021, 11:44pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/9 "2021-11-25T23:44:01Z")

</div>

Fan-bloomin’-tastic…! Thanks @KenWhitesell that’s nailed it! 👍👍

I can see myself fighting the urge to think in terms of the SQL that I’d write… getting there, slowly, bit by bit…!

Part of the reason I often try to construct a single SQL statement that does as much of the work for me as possible is because of race conditions, of course, so I’ll need to hone my understanding of when Django hits the database – I know I see a lot of references to that in the docs, so will continue to live half my waking hours delving into that 🙂

Thanks again for the help and bearing with me where I was finding it tricky to pin down what the issues was!

Je.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [November 25, 2021, 11:48pm UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/10 "2021-11-25T23:48:04Z")

</div>

> [@LJE2](#):
>
> I can see myself fighting the urge to think in terms of the SQL that I’d write… getting there, slowly, bit by bit…!

I still do - after all, I’ve been writing SQL since 1987.

Fortunately, the Python syntax used by Django allows you chain most expressions together as a single statement if that’s how you want to write them.  
But either way, everything you need to know about that topic is summarized by the phrase “[Querysets are lazy](https://docs.djangoproject.com/en/3.2/topics/db/queries/#querysets-are-lazy)”.

---

<div class="post-metadata">

**Author:** ![pmpr88](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/pmpr88/32/7727_2.png) [@pmpr88](https://forum.djangoproject.com/u/pmpr88)\
**Post date:** [March 8, 2022, 10:11am UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/11 "2022-03-08T10:11:02Z")

</div>

i have a many-to-many to it self

```auto
class Article_Version_Child(BaseModel):
    from_article_version = models.ForeignKey(ArticleVersion, on_delete=models.CASCADE, related_name='from_article_version')
    to_article_version = models.ForeignKey(ArticleVersion, on_delete=models.CASCADE, related_name='to_article_version')
    quantity = models.IntegerField(verbose_name="Quantidade", null=True, blank=True, default=1)

```

i already tried many ways, but i cant get the quantity, i always get “‘ArticleVersion’ object has no attribute ‘article\_version\_child\_set’”

Examples:  
article\_version.article\_version\_child\_set.all()  
article\_version.articleversionchild\_set.get(from\_article\_version=OtherArticleVersion)

---

<div class="post-metadata">

**Author:** ![pmpr88](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/pmpr88/32/7727_2.png) [@pmpr88](https://forum.djangoproject.com/u/pmpr88)\
**Post date:** [March 17, 2022, 10:36am UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/12 "2022-03-17T10:36:13Z")

</div>

Anybody know if is possible get Extra Fields in a ManyToMany with self?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [March 17, 2022, 11:41am UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/13 "2022-03-17T11:41:33Z")

</div>

This topic has been marked as solved. If you have a question or issue, please open a new topic.

---

<div class="post-metadata">

**Author:** ![pmpr88](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/pmpr88/32/7727_2.png) [@pmpr88](https://forum.djangoproject.com/u/pmpr88)\
**Post date:** [March 17, 2022, 11:55am UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/14 "2022-03-17T11:55:46Z")

</div>

Thanks, done.

> [@Extra fields on many-to-many relationships¶](https://forum.djangoproject.com/t/extra-fields-on-many-to-many-relationships/12663):
>
> i have a many-to-many to it self, and i try access the same information by querying the [many-to-many reverse relationship] from my Model object, like in documentation. But not works, always get “object has no attribute”. Its because its a many-to-many to it self? Is there a solution, or workaround? Another way to access the same information is by querying the [many-to-many reverse relationship](https://docs.djangoproject.com/en/dev/topics/db/queries/#m2m-reverse-relationships) from a Person object: \>\>\> ringos\_membership = ringo.membership\_set.get(group=beatles) \>\>\> ringos\_…

---

<div class="post-metadata">

**Author:** ![s8186255](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/s8186255/32/11374_2.png) [@s8186255](https://forum.djangoproject.com/u/s8186255)\
**Post date:** [December 19, 2022, 9:55am UTC](https://forum.djangoproject.com/t/reading-extra-fields-in-a-manytomany-through-table/10676/15 "2022-12-19T09:55:49Z")

</div>

if you develop a chat app with user and chat room having a many to many relation and you want to know what time a user join the room,you could use a extra field such as joined\_at in many to many table.
