Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Relationships

I'm new at Django and have a few problems getting my mind around manytomany relatiosnhips and Manytoone (i.e Foreign key).

My setup is this.

I have class A, Class B, Class C

Every Class B object must belong to a Class A object. They cannot belong to more than one Class A object. A more practical example could be if Class A is a Music Band and class B is a song with that Band. Most Bands will have more than one song but every song must belong to a Band (in this example a song can never have multiple Bands).

Class C is a listing of individual Band members. So every band member can be associated with an arbitrary number of songs as well as an arbitrary number of Bands. In other words a member of Band X can also be a member of Band Y.

My question then would be

How would i use the ForeignKey and ManytoMany relationships in this context?

This example is contrived just to make my situation easier to understand and to help me explain my issue. I would like the admin to display for each Class C object what Class B objects or Class A objects that Class C belongs go. The same goes for Class B and Class A.

If you look at Class A objects you should be able to se a listing of all Class B objects that belong to that particular Class A object.

Any and all input appreciated.

like image 562
Consiglieri Avatar asked Sep 16 '09 12:09

Consiglieri


1 Answers

Here's how I'd set it up (in your models.py)

class Member(models.Model):
   name = models.CharField(max_length=100)
   ...

   def __unicode__(self):
       return self.name


class Band(models.Model):
   name = models.CharField(max_length=100)
   members = models.ManyToManyField(Member)
   ... 

   def __unicode__(self):
       return self.name


class Song(models.Model):
   name = models.CharField(max_length=100)
   band = models.ForeignKey(Band)
   ...

   def __unicode__(self):
       return self.name

Set up like this:

  • member.band_set.all() gives you all bands a member belongs to
  • band.members.all() gives you the members of a band
  • song.band gives you the band for that song
  • band.song_set.all() gives you all songs for a band

Note that the band_set on member and the song_set on band are "reverse" relationships. They aren't explicitly defined in the models, but Django sets them up for you transparently. You can customize these by using the related_name parameter on the field definition. Example:

class Band(models.Model):
   members = models.ManyToManyField(Member,related_name='bands')

would let you get all the bands for a member as follows:

member.bands.all()

The admin will automatically provide the following:

  • Show all members for a band in a multi-select list
  • Show the band for a song in a single select list

However, if you want to see songs for a band, you'll have to do a little admin customization.

In your admin.py:

from django.contrib import admin

class SongInline(admin.StackedInline):
    model = Song
    extra = 1

class BandAdmin(admin.ModelAdmin):
    inlines = [SongInline]

admin.site.register(Band,BandAdmin)
admin.site.register(Member)
admin.site.register(Song)

This will let you view the songs right from the admin page -- and edit or add them as well! By following this template you could show all bands for a member as well.

You can get a more detailed introduction to the admin customization at http://docs.djangoproject.com/en/dev/intro/tutorial02/

like image 112
Matthew Christensen Avatar answered Sep 20 '22 22:09

Matthew Christensen