djangodjango-polymorphic

Make primary key unique across multiple child classes with common parent


I have a django-polymorphic model like this:

from polymorphic.models import PolymorphicModel

class Item(PolymorphicModel):
    sku = models.CharField(primary_key=True, max_length=32)

class Car(Item):
    pass

class Boat(Item):
    pass

To my horror, it's possible to create instances of the subclasses with the same primary key:

Car.objects.create(sku='123')
Boat.objects.create(sku='123') # Does NOT crash but I want it to

But of course, trying to access the created object will fail horribly:

>>> Car.objects.get(sku='123')
polymorphic.models.PolymorphicTypeInvalid: ContentType 42 for <class 'demo_application.models.Car'> #123 does not point to a subclass!

How do I ensure that all instances of Item have a unique primary key?

One option I considered is overriding the save methods of Car & Boat, or listening to pre_save signals. However, that would add a database request whenever I save them, and it feels like a hacky solution.


Solution

  • I would change one line

    sku = models.CharField(unique=True, max_length=32)
    

    It's not recommended to use a field as the primary key in child models within Django. Doing so can lead to unexpected behavior because Django automatically creates and uses *_ptr_id as the primary key for child models

    UPDATE: I recommend using django-typed-models, this will ensure unique Primary Key for every subclass, you will not be able to set the same primary key to two objects.