Ivan Radovanovic
Ivan Radovanovic

Reputation: 11

How to create many-to-one relation with django and to display it in admin interface

I have the following problem - I would like to create many-to-one mapping in django to represent what is basically relation between object and pieces of object like:

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

class WebsiteIp(models.Model):
    website = models.ForeignKey(Website, primary_key = True)
    ip = models.CharField(max_length = 40, primary_key = True)
    introduction_date = models.DateField()

which should all be presented on website (parent object) editing page. Although it sounds like trivial problem I couldn't really find anything useful on this

Upvotes: 1

Views: 2582

Answers (2)

Ivan Radovanovic
Ivan Radovanovic

Reputation: 11

Work around this problem is to modify primary key settings on dependant relation (but that works only in cases like this - when there is one piece of key that might be unique for entire table (ip in this case)).

class WebsiteIp(models.Model):
    website = models.ForeignKey(Website)
    ip = models.CharField(max_length = 40, primary_key = True)
    introduction_date = models.DateField()

After this (and only after this), part of solution proposed by mkoistinen would work in expected way. General problem is that django is checking ability to create new objects by examining uniqueness of primary key columns (in a wrong way), so I guess it is possible to fix that too by overriding some of models.Model methods, but I don't know enough about django internals to be able to point what method.

Upvotes: 0

mkoistinen
mkoistinen

Reputation: 7773

Add the related_name parameter to your ForeignKey on WebsiteIP like so:

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

class WebsiteIp(models.Model):
    website = models.ForeignKey(Website, primary_key = True, related_name="IPs")
    ip = models.CharField(max_length = 40)
    introduction_date = models.DateField()

Then, you can reference the IPs as a many-to-one mapping from Website like so:

website = Website.objects.filter(name="blah")
if website.count():
  IPs = website[0].IPs

Untested of course, but this should get you in the right direction. Also check out: https://docs.djangoproject.com/en/dev/topics/db/models/#many-to-one-relationships

In your admin.py, where you presumably have something like this:

class WebsiteAdmin(admin.ModelAdmin):
  list_display = ('name',)
  search_fields = ['name']
  ordering = ('name', )

Update to the following:

class WebsiteIpInline(admin.TabularInline):
  model = WebsiteIp
  extra = 1

class WebsiteAdmin(admin.ModelAdmin):
  list_display = ('name',)
  search_fields = ['name']
  inlines = ( WebsiteIpInline, )
  ordering = ('name', )

Should display what you want!

Upvotes: 3

Related Questions