Django Model field with multiple types?
I have the following (simplified) models:
class Structure(models.Model):
name=models.CharField(max_length=100, unique=True)
class Unit(models.Model):
name=models.CharField(max_length=100, unique=True)
Each model, also has a builtFrom field, which shows what the item is built from, for example:
class Unit(models.Model):
name=models.CharField(max_length=100, unique=True)
builtFrom=models.ForeignKey(Structure)
However, builtFrom can be populated from either a Unit type, or a Structure type. Is there an easy way to represent this in my models?
The only thing I can think of is to have a separate model开发者_运维知识库, like so:
class BuiltFromItem(models.Model):
structure=models.ForeignKey(Structure)
unit=models.ForeignKey(Structure)
class Unit(models.Model):
name=models.CharField(max_length=100, unique=True)
builtFrom=models.ForeignKey(BuiltFromItem)
And then have one of the BuiltFromItem fields just be null. Then, when I need the data, figure out whether it is a structure or unit that it is built from. Is there a better solution for this?
You want what the Django docs refer to as a "generic relation". Support for them is built into Django.
Generic relation is probably the best approach, yet it can be a little problematic, if you're planning to manage such models via admin panel. You would then have to add a ModelInline to the models, that generic relation is pointing to, but as far as I know (correct me if I'm wrong), there's no convenient way of picking related object from the other side (from model, where relation is defined), other than choosing model class and manually typing instance primary key.
Picking the best solution actually depends on structure of your models and on what they have in common. Another idea I have, is to use Multi-table inheritance, by defining some BasicObject
that is a parent object to Structure
and Unit
models:
class BasicObject(models.Model):
name=models.CharField(max_length=100, unique=True)
#other common data
builtFrom=models.ForeignKey('BasicObject')
class Structure(BasicObject):
#data specific to Structure
class Unit(BasicObject):
#data specific to Unit
Now all Structure
and Unit
object will also be BasicObject
instances, and you will be able to populate builtFrom
field with proper BasicObject
instance. It makes queries more expensive, because data is divided into two diffrent tables, so you should consider if this approach is beneficial in your case.
精彩评论