简体   繁体   中英

Implementing polymorphic associations on an inventory database

I'm trying to design an Inventory table on a database (Django + PostgreSQL) and I came to a doubt as to which is the most "correct" way to implement multiple polymorphic relationships with other tables.

Basically, each entry needs to have an input field which can refer to any of a set of tables: for example, a product could have been purchased (and therefore this field should be a Foreign Key for the PurchaseOrder table), or it could have been produced/manufactured (ie ProductionOrder ). Similarly, it will eventually have an output which could, for instance, refer to a SalesOrder (if the product is sold) or another ProductionOrder (if it is used to manufacture another thing).

Of course a single Foreign Key field cannot refer to entries in different tables, so what is the best way to achieve this? I read answers to similar questions, but the suggestions didn't seem to be well-suited for a case like this. Creating intermediate tables doesn't seem appropiate since sales and production orders don't belong to the same "superset", at least to me.

My current thought is to have as many fields as possible options (ie idProductionOrder , idSalesOrder ) for both inputs and outputs, and add a -NAND- constraint to avoid both fields to contain data simultaneously. I see this could be a practical solution, but perhaps not a very neat one. Is there a better approach?

I think what you are looking for is the GenericForeignKey field. This can point to different models. Here an example based on your input:

class YourModel(models.Model):
    limit = (models.Q(app_label = 'YourApp', model = 'ProductionOrder') |
             models.Q(app_label = 'YourApp', model = 'SalesOrder ')  |
             models.Q(app_label = 'YourApp',model = 'ProductionOrder '))

    content_type = models.ForeignKey(ContentType, limit_choices_to = limit)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

See the docu

If you want them to integrate nicely into the admin you should also consider using django-smart-selects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM