使用具有“通用目的”的模型字段来建模继承 [英] Using a Model with "general purpose" fields to model inheritance
问题描述
我目前正在围绕如何使用Django对某些东西进行建模。基本的情况是,我有一个对象应该作为一个机箱
并提供一些套接字
。然后有一些不同的模块
,它们放在底座的
套接字
code>。我想在Django中将这些不同的模块
模型作为不同的类建模,但在数据库层使用通用类,可能涉及一些通用字段。
所以数据库模型可能看起来像这样:
class Module(models.model):
/ pre>
name = models.CharField(max_length = 128)
#或者有更好的方式来注释类型?
type = models.CharField(max_length = 128)
string1 = models.CharField(max_length = 128)
string2 = models.CharField(max_length = 128)
...
int1 = models.IntegerField()
#从模块
#派生的某种引擎类,但没有别的,然后将通用
#字段映射
class Socket(models.Model):
is_on = models.ForeignKey(Chassis)
name = models.CharField(max_length = 128)
type = models.CharField(max_length = 128)
class连接(models.Model):
chassis = models.ForeignKey(Chassis)
module = models.ForeignKey(Module)
via = models.ForeignKey(Socket)
class Chassis(models.Model):
name = models.CharField(max_length = 128)
modules = models.ManyToManyField模块,通过='连接')
类组(models.Model):
name = models.CharField(max_length = 128)
当然,我不想破坏我的逻辑与这种非规范化。这就是为什么我暗示应该使用模块表的某种
引擎
类,而是提供逻辑getter和setter,有效地将数据(如Horsepower)映射到int1
所以我的问题是基本的:
- 与Django?或者是否有更好的(可能内置的)方式来处理这个问题?
- 可以构造正确的类型,为非规范化模型提供包装方法,具体取决于
Module.type
字段自动?
Django正在做什么? / p>
一般的想法是可以的,但是非规范化可能会使你的查询不是最佳的。标准解决方案是为每种类型的模块子类 Module
这将创建一个模块
表加上一个具有特定类型的模块类型的表。这当然是假设您不会在运行时创建或删除模块类型。
说到你的模型有一些问题:
class Module(models.model):
name = models.CharField(max_length = 128)
#还是有更好的方式来注释类型?
type = models.CharField(max_length = 128)
string1 = models.CharField(max_length = 128)
string2 = models.CharField(max_length = 128)
...
int1 = models.IntegerField()
通常, type
将被归一化以节省空间:
class ModuleType(models.model):
name = models.CharField(max_length = 128)
#任何其他类型特定的参数。
class Module(models.model):
name = models.CharField(max_length = 128)
type = models.ForeignKey(ModuleType,related_name =modules)
string1 = models.CharField(max_length = 128)
string2 = models.CharField(max_length = 128)
...
int1 = models.IntegerField()
class Socket(models.Model) :
is_on = models.ForeignKey(Chassis)
name = models.CharField(max_length = 128)
type = models.CharField(max_length = 128)
class连接(models.Model):
chassis = models.ForeignKey(Chassis)
module = models.ForeignKey(Module)
via = models.ForeignKey(Socket)
class Chassis(models.Model):
name = models.CharField(max_length = 128)
sockets = m
modules = models.ManyToManyField(Model,through ='Socket')
底盘
是一团糟。您没有定义套接字
,写下模型
您可能想要的模块
c $ c通过应该可以参考 Connection
(a through
model必须在链接的两端都有 ForeignKey
s)。但是从你的描述中,我得到的简单得多:
class Socket(models.Model):
chassis = models .ForeignKey(Chassis,related_name =sockets)
name = models.CharField(max_length = 128)
#是type一个ModuleType?如果是,请使用ForeignKey。
#如果没有,创建一个SocketType模型。
type = models .___
module = models.ForeignKey(Module,related_name =sockets)
class Chassis(models.Model):
name = models .CharField(max_length = 128)
sockets = models.IntegerField()
modules = models.ManyToManyField(Socket)
更好地描述您正在建模的内容,这可以进一步改进。例如,我不知道一个ManyToMany是你想要的。您可能需要从机箱的实例拆分机箱的设计(例如,给定类型的机箱的所有实例(包括其插座)的所有实例的常见功能)将参考设计,并将另一个表映射到模块的套接字)。
可以根据Module.type字段自动构建正确的类型?
这是工厂设计模式。在Python中,您将实现它作为构造函数的字典:
class Module(models.model):
#...
CONSTRUCTORS = {}
@staticmethod
def register_constructor(type_name,constructor):
Module.CONSTRUCTORS [type_name] =构造函数
def construct(self):
return Module.CONSTRUCTORS [self.type.name](self)
我不认为你需要一个特定的引擎类;各种模块类就足够了。
I am currently kidding around on how to model something using Django. The basic situation is that I have an object that should serve as a chassis
and provide some sockets
. Then there are loads of different modules
that are placed on the sockets
of a chassis
. I would like to model these different modules
as distinct classes in Django, but use a common class on the database layer, possibly involving some generic fields.
So the database model might look something like this:
class Module(models.model):
name = models.CharField(max_length=128)
# Or is there a better way to annotate a type?
type = models.CharField(max_length=128)
string1 = models.CharField(max_length=128)
string2 = models.CharField(max_length=128)
...
int1 = models.IntegerField()
# Some kind of engine class that derives from Module
# but does nothing else then "mapping" the generic
# fields to something sensible
class Socket(models.Model):
is_on = models.ForeignKey(Chassis)
name = models.CharField(max_length=128)
type = models.CharField(max_length=128)
class Connection(models.Model):
chassis = models.ForeignKey(Chassis)
module = models.ForeignKey(Module)
via = models.ForeignKey(Socket)
class Chassis(models.Model):
name = models.CharField(max_length=128)
modules= models.ManyToManyField(Module, through='Connection')
class Group(models.Model):
name = models.CharField(max_length=128)
Of course I wouldn't want to spoil my logic with this denormalization. Thats why I hinted for some kind of engine
class that should use the Module table, but provide "logical" getters and setters, effectively mapping data like "Horsepower" to "int1".
So my questions are basicly:
- Is what I am doing reasonable with Django? Or is there a better (possibly built in) way to deal with this?
- Would it be possible to construct the correct type, the one providing the wrapper methods for the denormalized model, depending on the
Module.type
field automatically?
Is what I am doing reasonable with Django?
The general idea is okay, but the denormalization may make your queries less than optimal. The standard solution would be to subclass Module
for each type of module; this would create a module
table plus a table per module type with the type-specific stuff. This, of course, assumes you won't be creating or deleting module types at runtime.
That said, there are some issues with your models:
class Module(models.model):
name = models.CharField(max_length=128)
# Or is there a better way to annotate a type?
type = models.CharField(max_length=128)
string1 = models.CharField(max_length=128)
string2 = models.CharField(max_length=128)
...
int1 = models.IntegerField()
Normally, type
would get normalized to save space:
class ModuleType(models.model):
name = models.CharField(max_length=128)
# Any other type-specific parameters.
class Module(models.model):
name = models.CharField(max_length=128)
type = models.ForeignKey(ModuleType, related_name="modules")
string1 = models.CharField(max_length=128)
string2 = models.CharField(max_length=128)
...
int1 = models.IntegerField()
class Socket(models.Model):
is_on = models.ForeignKey(Chassis)
name = models.CharField(max_length=128)
type = models.CharField(max_length=128)
class Connection(models.Model):
chassis = models.ForeignKey(Chassis)
module = models.ForeignKey(Module)
via = models.ForeignKey(Socket)
class Chassis(models.Model):
name = models.CharField(max_length=128)
sockets = m
modules= models.ManyToManyField(Model, through='Socket')
Chassis
is a mess. You didn't define sockets
, wrote Model
where you probably want module
, and through
should probably refer to Connection
(a through
model has to have ForeignKey
s to both ends of the link). But from your description, I get the far simpler:
class Socket(models.Model):
chassis = models.ForeignKey(Chassis, related_name="sockets")
name = models.CharField(max_length=128)
# Is `type` a ModuleType? If so, use a ForeignKey.
# If not, create a SocketType model.
type = models.___
module = models.ForeignKey(Module, related_name="sockets")
class Chassis(models.Model):
name = models.CharField(max_length=128)
sockets = models.IntegerField()
modules = models.ManyToManyField(Socket)
With a better description of what you're modeling, this can be refined further. For example, I'm not sure a ManyToMany is what you want. You may need to split the design of a chassis (i.e. things common to all instances of a given kind of chassis, including its sockets) from the instances of that chassis (which would reference the design, and have another table mapping sockets to modules).
Would it be possible to construct the correct type depending on the Module.type field automatically?
That's the Factory design pattern. In Python, you'd implement it as a dictionary of constructors:
class Module(models.model):
# ...
CONSTRUCTORS = {}
@staticmethod
def register_constructor(type_name, constructor):
Module.CONSTRUCTORS[type_name] = constructor
def construct(self):
return Module.CONSTRUCTORS[self.type.name](self)
I don't think you need a specific engine class; the various module classes will suffice.
这篇关于使用具有“通用目的”的模型字段来建模继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!