#

## Django documentation

# 9. Many-to-many relationships via an intermediary table

For many-to-many relationships that need extra fields on the intermediary table, use an intermediary model.

In this example, an `Article` can have multiple `Reporter``s, and each ``Article`-`Reporter` combination (a `Writer`) has a `position` field, which specifies the `Reporter`'s position for the given article (e.g. "Staff writer").

## Model source code

    from django.core import meta

    class Reporter(meta.Model):
        first_name = meta.CharField(maxlength=30)
        last_name = meta.CharField(maxlength=30)

        def __repr__(self):
            return "%s %s" % (self.first_name, self.last_name)

    class Article(meta.Model):
        headline = meta.CharField(maxlength=100)
        pub_date = meta.DateField()

        def __repr__(self):
            return self.headline

    class Writer(meta.Model):
        reporter = meta.ForeignKey(Reporter)
        article = meta.ForeignKey(Article)
        position = meta.CharField(maxlength=100)

        def __repr__(self):
            return '%r (%s)' % (self.get_reporter(), self.position)

## API reference

### Reporter objects have the following methods:

- `add_writer()`
- `delete()`
- `get_writer()`
- `get_writer_count()`
- `get_writer_list()`
- `save()`

### Article objects have the following methods:

- `add_writer()`
- `delete()`
- `get_next_by_pub_date()`
- `get_previous_by_pub_date()`
- `get_writer()`
- `get_writer_count()`
- `get_writer_list()`
- `save()`

### Writer objects have the following methods:

- `delete()`
- `get_article()`
- `get_reporter()`
- `save()`

## Sample API usage

This sample code assumes the above models have been saved in a file `examplemodel.py`.

    >>> from django.models.examplemodel import reporters, articles, writers

    # Create a few Reporters.
    >>> r1 = reporters.Reporter(first_name='John', last_name='Smith')
    >>> r1.save()
    >>> r2 = reporters.Reporter(first_name='Jane', last_name='Doe')
    >>> r2.save()

    # Create an Article.
    >>> from datetime import datetime
    >>> a = articles.Article(headline='This is a test', pub_date=datetime(2005, 7, 27))
    >>> a.save()

    # Create a few Writers.
    >>> w1 = writers.Writer(reporter=r1, article=a, position='Main writer')
    >>> w1.save()
    >>> w2 = writers.Writer(reporter=r2, article=a, position='Contributor')
    >>> w2.save()

    # Play around with the API.
    >>> a.get_writer_list(order_by=['-position'], select_related=True)
    [John Smith (Main writer), Jane Doe (Contributor)]
    >>> w1.get_reporter()
    John Smith
    >>> w2.get_reporter()
    Jane Doe
    >>> w1.get_article()
    This is a test
    >>> w2.get_article()
    This is a test
    >>> r1.get_writer_list()
    [John Smith (Main writer)]

## Comments

### cuu508 August 25, 2005 at 4:02 p.m.

In admin interface, using edit_inline, one can add reporters to article by selecting them from dropdown list.
What about other choices (if I have 1000 reporters, dropdown is inefficient) like the js filter for ManyToMany or custom lookup popup - are these possible?

### Adrian Holovaty August 25, 2005 at 10:42 p.m.

cuu508: Use "raw_id_admin=True" on the ForeignKey field to accomplish that.

### cuu508 August 25, 2005 at 11:10 p.m.

Great, thanks!

### Sebastien Fievet September 21, 2005 at 8:16 a.m.

What do i have to do in order to don't have an 'id' field into the intermediary table ?

### Antonio Rodriguez October 20, 2005 at 9:53 a.m.

If I've got a Many2Many relationship implemented via an intermediary table (a la http://www.djangoproject.com/documentati...) but in the intermediary table I point back to the same table twice, does django's ORM not support this?

Example: table Node, intermediary table Relationship that wants to point back to Node twice (once as attribute 'child' and once as attribute 'parent'). It seems like what I get is the ability to see just one of the references back (the first one declared in the model object), so with a call like Node.get_relationship_list(parent__id__exact=x) I get nothing even if it is there.

## Post a comment

Note: Please only use the comments for questions/critcisms/suggestions on the docs; if you experience errors please file a ticket, ask in the IRC channel, or post to the django-users list. Comments will be periodically reviewed, integrated into the documentation proper, and removed.

Your name:

Comment: