Django

Code

Ticket #7918 (closed: fixed)

Opened 4 months ago

Last modified 3 months ago

Allow ForeignKey to a parent class when using inlines

Reported by: sil Assigned to: brosner
Milestone: 1.0 Component: Database layer (models, ORM)
Version: SVN Keywords:
Cc: arnaud.rebts@gmail.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 1
Needs tests: 1 Patch needs improvement: 0

Description (Last modified by brosner)

At the moment, if you have a hierarchy:

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

(as per http://www.djangoproject.com/documentation/model-api/#multi-table-inheritance), it doesn't interact all that well with inlined ForeignKeyed? models. Imagine you had:

class Owner:
    name = models.CharField(max_length=100)
    place = models.ForeignKey(Place)

(so a Place can have multiple Owners). This also works fine with Restaurants, because every Restaurant is-a Place. However, if you want to inline the Owners:

class OwnerInline(admin.TabularInline): 
    model = Owner
    extra = 5

class PlaceAdmin(admin.ModelAdmin):
    model = Place
    inlines = [OwnerInline]

then this won't work; if you try and create a Restaurant, you get a complaint that Owner has no ForeignKey? to Restaurant (because technically it doesn't). This is because (new)forms._get_foreign_key checks that the ForeignKey? points to this model itself, where it should really be checking whether the ForeignKey? points to this model or any of its ancestor classes. The attached patch rectifies this.

Attachments

subclass-foreignkey.patch (1.3 kB) - added by sil on 07/23/08 11:59:45.
Updated to handle fail

Change History

07/23/08 11:28:43 changed by sil

  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

mrph. Code from above in code formatting. Sorry.

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField?()

class Owner:
    name = models.CharField(max_length=100)
    place = models.ForeignKey(Place)

class OwnerInline(admin.TabularInline):
    model = Owner
    extra = 5

class PlaceAdmin(admin.ModelAdmin):
    model = Place
    inlines = [OwnerInline]

07/23/08 11:29:04 changed by sil

  • needs_better_patch set to 1.
  • needs_tests set to 1.
  • needs_docs set to 1.

07/23/08 11:50:51 changed by brosner

  • description changed.

Fixed ticket description formatting.

07/23/08 11:54:12 changed by brosner

  • owner changed from nobody to brosner.
  • status changed from new to assigned.
  • version changed from newforms-admin to SVN.
  • stage changed from Unreviewed to Accepted.

07/23/08 11:54:19 changed by brosner

  • milestone set to 1.0 beta.

07/23/08 11:59:45 changed by sil

  • attachment subclass-foreignkey.patch added.

Updated to handle fail

07/23/08 12:01:06 changed by sil

Updated patch to handle the OneToOneField? value being null when you're first adding a Restaurant, which blows up because it's not a nullable field (since it's a PK) but doesn't have a value (because the Restaurant isn't saved yet). Sorry.

07/23/08 12:01:31 changed by sil

  • needs_better_patch deleted.
  • stage changed from Accepted to Unreviewed.

07/23/08 12:12:13 changed by brosner

  • stage changed from Unreviewed to Accepted.

Don't change the stage. That is reserved for ticket triagers and committers. The ticket itself is accepted, you don't need to do that when you upload a new patch. The needs_better_patch is meant for that :)

07/24/08 06:40:08 changed by sil

Cool -- I figured that the newer patch wasn't reviewed :) no problem!

08/01/08 11:51:10 changed by brosner

It is likely [8165] has fixed this. Can someone verify? Perhaps a test case should be ordered :)

08/01/08 11:51:15 changed by brosner

  • milestone changed from 1.0 beta to 1.0.

08/07/08 10:55:43 changed by Arnaud Rebts

  • cc set to arnaud.rebts@gmail.com.

It seems to be working now if the ForeinKey? is in the direct super class, but not if it's in a higher class.

So, this is working:

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField()
    serves_pizza = models.BooleanField()

class Owner(models.Model):
    name = models.CharField(max_length=100)
    place = models.ForeignKey(Place)

class OwnerInline(admin.TabularInline): 
    model = Owner
    extra = 5

class PlaceAdmin(admin.ModelAdmin):
    model = Place
    inlines = [OwnerInline]

class RestaurantAdmin(admin.ModelAdmin):
    model = Restaurant
    inlines = [OwnerInline]

But not this:

class ItalianRestaurant(Restaurant):
    pass

class ItalianRestaurantAdmin(admin.ModelAdmin):
    model = ItalianRestaurant
    inlines = [OwnerInline]

08/27/08 18:06:24 changed by jacob

  • component changed from Uncategorized to Database wrapper.

08/29/08 12:41:41 changed by brosner

  • status changed from assigned to closed.
  • resolution set to fixed.

(In [8708]) Fixed #7918 -- Allow the foreign key in an inline to be any where in the parent chain. Thanks sil for the report.


Add/Change #7918 (Allow ForeignKey to a parent class when using inlines)




Change Properties
Action