使用具有“通用目的”的模型字段来建模继承 [英] Using a Model with "general purpose" fields to model inheritance

查看:148
本文介绍了使用具有“通用目的”的模型字段来建模继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在围绕如何使用Django对某些东西进行建模。基本的情况是,我有一个对象应该作为一个机箱并提供一些套接字。然后有一些不同的模块,它们放在底座的套接字 code>。我想在Django中将这些不同的模块模型作为不同的类建模,但在数据库层使用通用类,可能涉及一些通用字段。



所以数据库模型可能看起来像这样:

  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()

#从模块
#派生的某种引擎类,但没有别的,然后将通用
#字段映射

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)
/ pre>

当然,我不想破坏我的逻辑与这种非规范化。这就是为什么我暗示应该使用模块表的某种引擎类,而是提供逻辑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 ForeignKeys 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆